ObjFW  Diff

Differences From Artifact [8bf9db28f4]:

To Artifact [c8cb26401f]:


663
664
665
666
667
668
669

















































670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714


















715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
	if (cls == Nil)
		return NULL;

	dummy.isa = cls;
	return objc_msg_lookup_stret((id)&dummy, sel);
}


















































const char*
class_getMethodTypeEncoding(Class cls, SEL sel)
{
	struct objc_method_list *ml;
	struct objc_category **cats;

	if (cls == Nil)
		return NULL;

	objc_global_mutex_lock();

	for (ml = cls->methodlist; ml != NULL; ml = ml->next) {
		for (unsigned int i = 0; i < ml->count; i++) {
			if (sel_isEqual((SEL)&ml->methods[i].sel, sel)) {
				const char *ret = ml->methods[i].sel.types;
				objc_global_mutex_unlock();
				return ret;
			}
		}
	}

	if ((cats = objc_categories_for_class(cls)) != NULL) {
		for (; *cats != NULL; cats++) {
			for (ml = (*cats)->instance_methods; ml != NULL;
			    ml = ml->next) {
				for (unsigned int i = 0; i < ml->count; i++) {
					if (ml->methods[i].sel.uid ==
					    sel->uid) {
						const char *ret =
						    ml->methods[i].sel.types;
						objc_global_mutex_unlock();
						return ret;
					}
				}
			}
		}
	}

	objc_global_mutex_unlock();

	if (cls->superclass != Nil)
		return class_getMethodTypeEncoding(cls->superclass, sel);

	return NULL;
}



















IMP
class_replaceMethod(Class cls, SEL sel, IMP newimp, const char *types)
{
	struct objc_method_list *ml;
	struct objc_category **cats;
	IMP oldimp;

	objc_global_mutex_lock();

	for (ml = cls->methodlist; ml != NULL; ml = ml->next) {
		for (unsigned int i = 0; i < ml->count; i++) {
			if (ml->methods[i].sel.uid == sel->uid) {
				oldimp = ml->methods[i].imp;

				ml->methods[i].imp = newimp;
				objc_update_dtable(cls);

				objc_global_mutex_unlock();

				return oldimp;
			}
		}
	}

	if ((cats = objc_categories_for_class(cls)) != NULL) {
		for (; *cats != NULL; cats++) {
			if (cls->info & OBJC_CLASS_INFO_METACLASS)
				ml = (*cats)->class_methods;
			else
				ml = (*cats)->instance_methods;

			for (; ml != NULL; ml = ml->next) {
				for (unsigned int i = 0; i < ml->count; i++) {
					if (ml->methods[i].sel.uid ==
					    sel->uid) {
						oldimp = ml->methods[i].imp;

						ml->methods[i].imp = newimp;
						objc_update_dtable(cls);

						objc_global_mutex_unlock();

						return oldimp;
					}
				}
			}
		}
	}

	/* FIXME: We need a way to free this at objc_exit() */
	if ((ml = malloc(sizeof(struct objc_method_list))) == NULL)
		OBJC_ERROR("Not enough memory to replace method!");

	ml->next = cls->methodlist;
	ml->count = 1;
	ml->methods[0].sel.uid = sel->uid;
	ml->methods[0].sel.types = types;
	ml->methods[0].imp = newimp;

	cls->methodlist = ml;

	objc_update_dtable(cls);

	objc_global_mutex_unlock();

	return NULL;
}

Class
object_getClass(id obj_)
{
	struct objc_object *obj;








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
<






<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
|
|
<
<
<
<









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|
<




|
<
<
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
|
<
<
|
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|







663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722

723
724
725
726
727
728









729







730

731
732




733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764

765
766
767
768
769


770

771
772












773






774
775


776

777





















778
779
780
781
782
783
784
785
786
787
	if (cls == Nil)
		return NULL;

	dummy.isa = cls;
	return objc_msg_lookup_stret((id)&dummy, sel);
}

static struct objc_method*
get_method(Class cls, SEL sel)
{
	struct objc_method_list *ml;
	struct objc_category **cats;

	for (ml = cls->methodlist; ml != NULL; ml = ml->next)
		for (unsigned int i = 0; i < ml->count; i++)
			if (sel_isEqual((SEL)&ml->methods[i].sel, sel))
				return &ml->methods[i];

	if ((cats = objc_categories_for_class(cls)) != NULL) {
		for (; *cats != NULL; cats++) {
			if (cls->info & OBJC_CLASS_INFO_METACLASS)
				ml = (*cats)->class_methods;
			else
				ml = (*cats)->instance_methods;

			for (; ml != NULL; ml = ml->next)
				for (unsigned int i = 0; i < ml->count; i++)
					if (sel_isEqual(
					    (SEL)&ml->methods[i].sel, sel))
						return &ml->methods[i];
		}
	}

	return NULL;
}

static void
add_method(Class cls, SEL sel, IMP imp, const char *types)
{
	struct objc_method_list *ml;

	/* FIXME: We need a way to free this at objc_exit() */
	if ((ml = malloc(sizeof(struct objc_method_list))) == NULL)
		OBJC_ERROR("Not enough memory to replace method!");

	ml->next = cls->methodlist;
	ml->count = 1;
	ml->methods[0].sel.uid = sel->uid;
	ml->methods[0].sel.types = types;
	ml->methods[0].imp = imp;

	cls->methodlist = ml;

	objc_update_dtable(cls);
}

const char*
class_getMethodTypeEncoding(Class cls, SEL sel)
{
	struct objc_method *method;


	if (cls == Nil)
		return NULL;

	objc_global_mutex_lock();










	if ((method = get_method(cls, sel)) != NULL) {







		const char *ret = method->sel.types;

		objc_global_mutex_unlock();
		return ret;




	}

	objc_global_mutex_unlock();

	if (cls->superclass != Nil)
		return class_getMethodTypeEncoding(cls->superclass, sel);

	return NULL;
}

bool
class_addMethod(Class cls, SEL sel, IMP imp, const char *types)
{
	bool ret;

	objc_global_mutex_lock();

	if (get_method(cls, sel) == NULL) {
		add_method(cls, sel, imp, types);
		ret = true;
	} else
		ret = false;

	objc_global_mutex_unlock();

	return ret;
}

IMP
class_replaceMethod(Class cls, SEL sel, IMP newimp, const char *types)
{
	struct objc_method *method;

	IMP oldimp;

	objc_global_mutex_lock();

	if ((method = get_method(cls, sel)) != NULL) {


		oldimp = method->imp;

		method->imp = newimp;
		objc_update_dtable(cls);












	} else {






		oldimp = NULL;
		add_method(cls, sel, newimp, types);


	}























	objc_global_mutex_unlock();

	return oldimp;
}

Class
object_getClass(id obj_)
{
	struct objc_object *obj;