+/**
+ * mono_object_isinst:
+ * @obj: an object
+ * @klass: a pointer to a class
+ *
+ * Returns: @obj if @obj is derived from @klass
+ */
+MonoObject *
+mono_object_isinst (MonoObject *obj, MonoClass *klass)
+{
+ MonoVTable *vt;
+ MonoClass *oklass;
+
+ if (!obj)
+ return NULL;
+
+ vt = obj->vtable;
+ oklass = vt->klass;
+
+ if (!klass->inited)
+ mono_class_init (klass);
+
+ if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ if ((klass->interface_id <= oklass->max_interface_id) &&
+ vt->interface_offsets [klass->interface_id])
+ return obj;
+ } else {
+ if (oklass->rank && oklass->rank == klass->rank) {
+ if ((oklass->element_class->baseval - klass->element_class->baseval) <=
+ klass->element_class->diffval)
+ return obj;
+ } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
+ return obj;
+ }
+
+ return NULL;
+}
+
+
+typedef struct {
+ MonoString *obj;
+ MonoString *found;
+} InternCheck;
+
+static void
+check_interned (gpointer key, MonoString *value, InternCheck *check)
+{
+ if (value == check->obj)
+ check->found = value;
+}
+
+MonoString*
+mono_string_is_interned (MonoString *o)
+{
+ InternCheck check;
+ check.obj = o;
+ check.found = NULL;
+
+ /*
+ * Yes, this is slow. Our System.String implementation needs to be redone.
+ * And GLib needs foreach() methods that can be stopped halfway.
+ */
+ g_hash_table_foreach (((MonoObject *)o)->vtable->domain->ldstr_table, (GHFunc)check_interned, &check);
+ return check.found;
+}
+
+MonoString*
+mono_string_intern (MonoString *str)
+{
+ GHashTable *ldstr_table;
+ MonoString *res;
+ char *ins = g_malloc (4 + str->length * 2);
+ char *p;
+ int bloblen;
+
+ /* Encode the length */
+ p = ins;
+ mono_metadata_encode_value (2 * str->length, p, &p);
+ bloblen = p - ins;
+ p = ins;
+ mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
+ bloblen = (p - ins) + 2 * str->length;
+ /*
+ * ins is stored in the hash table as a key and needs to have the same
+ * representation as in the metadata: we swap the character bytes on big
+ * endian boxes.
+ */
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ {
+ int i;
+ char *p2 = mono_array_addr (str->c_str, char, 0);
+ for (i = 0; i < str->length; ++i) {
+ *p++ = p2 [1];
+ *p++ = p2 [0];
+ p2 += 2;
+ }
+ }
+#else
+ memcpy (p, str->c_str->vector, str->length * 2);
+#endif
+ ldstr_table = ((MonoObject *)str)->vtable->domain->ldstr_table;
+ if ((res = g_hash_table_lookup (ldstr_table, ins))) {
+ g_free (ins);
+ return res;
+ }
+ g_hash_table_insert (ldstr_table, ins, str);
+ return str;
+}
+
+MonoString*
+mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 index)
+{
+ const char *str, *sig;
+ MonoString *o;
+ size_t len2;
+
+ sig = str = mono_metadata_user_string (image, index);
+ len2 = mono_metadata_decode_blob_size (str, &str);
+
+ if ((o = g_hash_table_lookup (domain->ldstr_table, sig)))
+ return o;
+
+ len2 >>= 1;
+
+ o = mono_string_new_utf16 (domain, (guint16*)str, len2);
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+ {
+ int i;
+ guint16 *p2 = (guint16*)mono_array_addr (o->c_str, guint16, 0);
+ for (i = 0; i < len2; ++i) {
+ *p2 = GUINT16_FROM_LE (*p2);
+ ++p2;
+ }
+ }
+#endif
+ g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
+
+ return o;
+}
+
+char *
+mono_string_to_utf8 (MonoString *s)
+{
+ char *as, *vector;
+ GError *error = NULL;
+
+ g_assert (s != NULL);
+
+ if (!s->length || !s->c_str)
+ return g_strdup ("");
+
+ vector = (char*)s->c_str->vector;
+
+ g_assert (vector != NULL);
+
+ as = g_utf16_to_utf8 ((gunichar2 *)vector, s->length, NULL, NULL, &error);
+
+ g_assert (!error);
+
+ return as;
+}
+
+char *
+mono_string_to_utf16 (MonoString *s)
+{
+ char *as;
+
+ g_assert (s != NULL);
+
+ as = g_malloc ((s->length * 2) + 2);
+ as [(s->length * 2)] = '\0';
+ as [(s->length * 2) + 1] = '\0';
+
+ if (!s->length || !s->c_str) {
+ return (as);
+ }
+
+ memcpy (as, mono_string_chars(s), s->length * 2);
+
+ return (as);
+}
+
+static void
+default_ex_handler (MonoException *ex)
+{
+ MonoObject *o = (MonoObject*)ex;
+ g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
+}
+
+static MonoExceptionFunc ex_handler = default_ex_handler;
+
+void
+mono_install_handler (MonoExceptionFunc func)
+{
+ ex_handler = func? func: default_ex_handler;
+}
+
+void
+mono_raise_exception (MonoException *ex)
+{
+ ex_handler (ex);
+}
+