1/* This file contains the implementation of class Protocol. 2 Copyright (C) 1993, 2004, 2009 Free Software Foundation, Inc. 3 4This file is part of GCC. 5 6GCC is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 3, or (at your option) 9any later version. 10 11GCC is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16Under Section 7 of GPL version 3, you are granted additional 17permissions described in the GCC Runtime Library Exception, version 183.1, as published by the Free Software Foundation. 19 20You should have received a copy of the GNU General Public License and 21a copy of the GCC Runtime Library Exception along with this program; 22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23<http://www.gnu.org/licenses/>. */ 24 25#include "objc/Protocol.h" 26#include "objc/objc-api.h" 27 28/* Method description list */ 29struct objc_method_description_list { 30 int count; 31 struct objc_method_description list[1]; 32}; 33 34 35@implementation Protocol 36{ 37@private 38 char *protocol_name; 39 struct objc_protocol_list *protocol_list; 40 struct objc_method_description_list *instance_methods, *class_methods; 41} 42 43/* Obtaining attributes intrinsic to the protocol */ 44 45- (const char *)name 46{ 47 return protocol_name; 48} 49 50/* Testing protocol conformance */ 51 52- (BOOL) conformsTo: (Protocol *)aProtocolObject 53{ 54 size_t i; 55 struct objc_protocol_list* proto_list; 56 57 if (aProtocolObject == nil) 58 return NO; 59 60 if (!strcmp(aProtocolObject->protocol_name, self->protocol_name)) 61 return YES; 62 63 for (proto_list = protocol_list; proto_list; proto_list = proto_list->next) 64 { 65 for (i=0; i < proto_list->count; i++) 66 { 67 if ([proto_list->list[i] conformsTo: aProtocolObject]) 68 return YES; 69 } 70 } 71 72 return NO; 73} 74 75/* Looking up information specific to a protocol */ 76 77- (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSel 78{ 79 int i; 80 struct objc_protocol_list* proto_list; 81 const char* name = sel_get_name (aSel); 82 struct objc_method_description *result; 83 84 if (instance_methods) 85 for (i = 0; i < instance_methods->count; i++) 86 { 87 if (!strcmp ((char*)instance_methods->list[i].name, name)) 88 return &(instance_methods->list[i]); 89 } 90 91 for (proto_list = protocol_list; proto_list; proto_list = proto_list->next) 92 { 93 size_t j; 94 for (j=0; j < proto_list->count; j++) 95 { 96 if ((result = [proto_list->list[j] 97 descriptionForInstanceMethod: aSel])) 98 return result; 99 } 100 } 101 102 return NULL; 103} 104 105- (struct objc_method_description *) descriptionForClassMethod:(SEL)aSel; 106{ 107 int i; 108 struct objc_protocol_list* proto_list; 109 const char* name = sel_get_name (aSel); 110 struct objc_method_description *result; 111 112 if (class_methods) 113 for (i = 0; i < class_methods->count; i++) 114 { 115 if (!strcmp ((char*)class_methods->list[i].name, name)) 116 return &(class_methods->list[i]); 117 } 118 119 for (proto_list = protocol_list; proto_list; proto_list = proto_list->next) 120 { 121 size_t j; 122 for (j=0; j < proto_list->count; j++) 123 { 124 if ((result = [proto_list->list[j] 125 descriptionForClassMethod: aSel])) 126 return result; 127 } 128 } 129 130 return NULL; 131} 132 133- (unsigned) hash 134{ 135 /* Compute a hash of the protocol_name; use the same hash algorithm 136 * that we use for class names; protocol names and class names are 137 * somewhat similar types of string spaces. 138 */ 139 int hash = 0, index; 140 141 for (index = 0; protocol_name[index] != '\0'; index++) 142 { 143 hash = (hash << 4) ^ (hash >> 28) ^ protocol_name[index]; 144 } 145 146 hash = (hash ^ (hash >> 10) ^ (hash >> 20)); 147 148 return hash; 149} 150 151/* 152 * Equality between formal protocols is only formal (nothing to do 153 * with actually checking the list of methods they have!). Two formal 154 * Protocols are equal if and only if they have the same name. 155 * 156 * Please note (for comparisons with other implementations) that 157 * checking the names is equivalent to checking that Protocol A 158 * conforms to Protocol B and Protocol B conforms to Protocol A, 159 * because this happens iff they have the same name. If they have 160 * different names, A conforms to B if and only if A includes B, but 161 * the situation where A includes B and B includes A is a circular 162 * dependency between Protocols which is forbidden by the compiler, so 163 * A conforms to B and B conforms to A with A and B having different 164 * names is an impossible case. 165 */ 166- (BOOL) isEqual: (id)obj 167{ 168 if (obj == self) 169 return YES; 170 171 if ([obj isKindOf: [Protocol class]]) 172 { 173 if (strcmp (protocol_name, ((Protocol *)obj)->protocol_name) == 0) 174 return YES; 175 } 176 177 return NO; 178} 179@end 180 181