API  0.9.10
CPObject.j
Go to the documentation of this file.
1 /*
2  * CPObject.j
3  * Foundation
4  *
5  * Created by Francisco Tolmasky.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
67 
68 
69 @protocol CPObject
70 
71 - (BOOL)isEqual:(id)object;
72 - (CPUInteger)hash;
73 
74 - (Class)superclass;
75 - (Class)class;
76 - (id)self;
77 
78 - (id)performSelector:(SEL)aSelector;
79 - (id)performSelector:(SEL)aSelector withObject:(id)object;
80 - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
81 
82 - (BOOL)isProxy;
83 
84 - (BOOL)isKindOfClass:(Class)aClass;
85 - (BOOL)isMemberOfClass:(Class)aClass;
86 - (BOOL)conformsToProtocol:(Protocol)aProtocol;
87 
88 - (BOOL)respondsToSelector:(SEL)aSelector;
89 
91 @optional
92 - (CPString)debugDescription;
93 
94 @end
95 
96 @protocol CPCoding
97 
98 - (void)encodeWithCoder:(CPCoder)aCoder;
99 - (id)initWithCoder:(CPCoder)aDecoder;
100 
101 @end
102 
103 @implementation CPObject <CPObject>
104 {
105  id isa;
106 }
107 
108 + (void)load
109 {
110 }
111 
112 + (void)initialize
113 {
114 // CPLog("calling initialize "+self.name);
115 }
116 
121 + (id)new
122 {
123  return [[self alloc] init];
124 }
125 
129 + (id)alloc
130 {
131 // CPLog("calling alloc on " + self.name + ".");
132  return class_createInstance(self);
133 }
134 
135 + (id)allocWithCoder:(CPCoder)aCoder
136 {
137  return [self alloc];
138 }
139 
144 - (id)init
145 {
146  return self;
147 }
148 
153 - (id)copy
154 {
155  return self;
156 }
157 
162 - (id)mutableCopy
163 {
164  return [self copy];
165 }
166 
170 - (void)dealloc
171 {
172 }
173 
174 // Identifying classes
178 + (Class)class
179 {
180  return self;
181 }
182 
186 - (Class)class
187 {
188  return isa;
189 }
190 
194 + (Class)superclass
195 {
196  return self.super_class;
197 }
198 
203 + (BOOL)isSubclassOfClass:(Class)aClass
204 {
205  var theClass = self;
206 
207  for (; theClass; theClass = theClass.super_class)
208  if (theClass === aClass)
209  return YES;
210 
211  return NO;
212 }
213 
218 - (BOOL)isKindOfClass:(Class)aClass
219 {
220  return [isa isSubclassOfClass:aClass];
221 }
222 
223 + (BOOL)isKindOfClass:(Class)aClass
224 {
225  return [self isSubclassOfClass:aClass];
226 }
227 
232 - (BOOL)isMemberOfClass:(Class)aClass
233 {
234  return self.isa === aClass;
235 }
236 
237 + (BOOL)isMemberOfClass:(Class)aClass
238 {
239  return self === aClass;
240 }
241 
246 - (BOOL)isProxy
247 {
248  return NO;
249 }
250 
251 // Testing class functionality
257 + (BOOL)instancesRespondToSelector:(SEL)aSelector
258 {
259  return !!class_getInstanceMethod(self, aSelector);
260 }
261 
267 - (BOOL)respondsToSelector:(SEL)aSelector
268 {
269  // isa is isa.isa in class case.
270  return !!class_getInstanceMethod(isa, aSelector);
271 }
272 
278 + (BOOL)instancesImplementSelector:(SEL)aSelector
279 {
280  var methods = class_copyMethodList(self),
281  count = methods.length;
282 
283  while (count--)
284  if (method_getName(methods[count]) === aSelector)
285  return YES;
286 
287  return NO;
288 }
289 
295 - (BOOL)implementsSelector:(SEL)aSelector
296 {
297  return [[self class] instancesImplementSelector:aSelector];
298 }
299 
305 + (BOOL)conformsToProtocol:(Protocol)aProtocol
306 {
307  return class_conformsToProtocol(self, aProtocol);
308 }
309 
315 - (BOOL)conformsToProtocol:(Protocol)aProtocol
316 {
317  return class_conformsToProtocol(isa, aProtocol);
318 }
319 
320 // Obtaining method information
321 
327 - (IMP)methodForSelector:(SEL)aSelector
328 {
329  return class_getMethodImplementation(isa, aSelector);
330 }
331 
337 + (IMP)instanceMethodForSelector:(SEL)aSelector
338 {
339  return class_getMethodImplementation(self, aSelector);
340 }
341 
347 - (CPMethodSignature)methodSignatureForSelector:(SEL)aSelector
348 {
349  // FIXME: We need to implement method signatures.
350  return nil;
351 }
352 
353 // Describing objects
358 {
359  return "<" + class_getName(isa) + " 0x" + [CPString stringWithHash:[self UID]] + ">";
360 }
361 
363 {
364  return class_getName(self.isa);
365 }
366 
367 // Sending Messages
373 - (id)performSelector:(SEL)aSelector
374 {
375  return self.isa.objj_msgSend0(self, aSelector);
376 }
377 
384 - (id)performSelector:(SEL)aSelector withObject:(id)anObject
385 {
386  return self.isa.objj_msgSend1(self, aSelector, anObject);
387 }
388 
396 - (id)performSelector:(SEL)aSelector withObject:(id)anObject withObject:(id)anotherObject
397 {
398  return self.isa.objj_msgSend2(self, aSelector, anObject, anotherObject);
399 }
400 
407 - (id)performSelector:(SEL)aSelector withObjects:(id)anObject, ...
408 {
409  var params = [self, aSelector].concat(Array.prototype.slice.apply(arguments, [3]));
410  return objj_msgSend.apply(this, params);
411 }
412 
413 - (id)forwardingTargetForSelector:(SEL)aSelector
414 {
415  return nil;
416 }
417 
418 // Forwarding Messages
425 - (void)forwardInvocation:(CPInvocation)anInvocation
426 {
427  [self doesNotRecognizeSelector:[anInvocation selector]];
428 }
429 
430 // Error Handling
436 - (void)doesNotRecognizeSelector:(SEL)aSelector
437 {
438  [CPException raise:CPInvalidArgumentException reason:
439  (class_isMetaClass(isa) ? "+" : "-") + " [" + [self className] + " " + aSelector + "] unrecognized selector sent to " +
440  (class_isMetaClass(isa) ? "class " + class_getName(isa) : "instance 0x" + [CPString stringWithHash:[self UID]])];
441 }
442 
443 // Archiving
452 - (id)awakeAfterUsingCoder:(CPCoder)aCoder
453 {
454  return self;
455 }
456 
461 - (Class)classForKeyedArchiver
462 {
463  return [self classForCoder];
464 }
465 
470 - (Class)classForCoder
471 {
472  return [self class];
473 }
474 
480 - (id)replacementObjectForArchiver:(CPArchiver)anArchiver
481 {
482  return [self replacementObjectForCoder:anArchiver];
483 }
484 
490 - (id)replacementObjectForKeyedArchiver:(CPKeyedArchiver)anArchiver
491 {
492  return [self replacementObjectForCoder:anArchiver];
493 }
494 
500 - (id)replacementObjectForCoder:(CPCoder)aCoder
501 {
502  return self;
503 }
504 
509 + (void)setVersion:(int)aVersion
510 {
511  class_setVersion(self, aVersion);
512 }
513 
517 + (int)version
518 {
519  return class_getVersion(self);
520 }
521 
522 // Scripting (?)
527 {
528  // FIXME: Why doesn't this work in KVO???
529  // return class_getName([self class]);
530  return isa.name;
531 }
532 
533 // Extras
538 - (id)autorelease
539 {
540  return self;
541 }
542 
546 - (unsigned)hash
547 {
548  return [self UID];
549 }
550 
551 - (CPString)UID
552 {
553  if (typeof self._UID === "undefined")
554  self._UID = objj_generateObjectUID();
555 
556  return self._UID + "";
557 }
558 
563 - (BOOL)isEqual:(id)anObject
564 {
565  return self === anObject || [self UID] === [anObject UID];
566 }
567 
572 - (id)retain
573 {
574  return self;
575 }
576 
580 - (void)release
581 {
582 }
583 
587 - (id)self
588 {
589  return self;
590 }
591 
595 - (Class)superclass
596 {
597  return isa.super_class;
598 }
599 
600 @end
601 
602 function CPDescriptionOfObject(anObject, maximumRecursionDepth)
603 {
604  if (anObject === nil)
605  return "nil";
606 
607  if (anObject === undefined)
608  return "undefined";
609 
610  if (anObject === window)
611  return "window";
612 
613  if (maximumRecursionDepth === 0)
614  return "...";
615 
616  if (anObject.isa)
617  {
618  if ([anObject isKindOfClass:CPString])
619  return '@"' + [anObject description] + '"';
620 
621  if ([anObject respondsToSelector:@selector(_descriptionWithMaximumDepth:)])
622  return [anObject _descriptionWithMaximumDepth:maximumRecursionDepth !== undefined ? maximumRecursionDepth - 1 : maximumRecursionDepth];
623 
624  return [anObject description];
625  }
626 
627  if (typeof(anObject) !== "object")
628  return String(anObject);
629 
630  var properties = [],
631  desc;
632 
633  for (var property in anObject)
634  if (anObject.hasOwnProperty(property))
635  properties.push(property);
636 
637  properties.sort();
638 
639  if (properties.length === 2 && anObject.hasOwnProperty("width") && anObject.hasOwnProperty("height"))
640  desc = [CPString stringWithFormat:@"CGSize: (%f, %f)", anObject.width, anObject.height];
641  else if (properties.length === 2 && anObject.hasOwnProperty("x") && anObject.hasOwnProperty("y"))
642  desc = [CPString stringWithFormat:@"CGPoint: (%f, %f)", anObject.x, anObject.y];
643  else if (properties.length === 2 && anObject.hasOwnProperty("origin") && anObject.hasOwnProperty("size"))
644  desc = [CPString stringWithFormat:@"CGRect: (%f, %f), (%f, %f)", anObject.origin.x, anObject.origin.y, anObject.size.width, anObject.size.height];
645  else if (properties.length === 4 && anObject.hasOwnProperty("top") && anObject.hasOwnProperty("right") && anObject.hasOwnProperty("bottom") && anObject.hasOwnProperty("left"))
646  desc = [CPString stringWithFormat:@"CGInset: { top:%f, right:%f, bottom:%f, left:%f }", anObject.top, anObject.right, anObject.bottom, anObject.left];
647  else
648  {
649  desc = "{";
650 
651  for (var i = 0; i < properties.length; ++i)
652  {
653  if (i === 0)
654  desc += "\n";
655 
656  var value = anObject[properties[i]],
657  valueDescription = CPDescriptionOfObject(value, maximumRecursionDepth !== undefined ? maximumRecursionDepth - 1 : maximumRecursionDepth).split("\n").join("\n ");
658 
659  desc += " " + properties[i] + ": " + valueDescription;
660 
661  if (i < properties.length - 1)
662  desc += ",\n";
663  else
664  desc += "\n";
665  }
666 
667  desc += "}";
668  }
669 
670  return desc;
671 }
void doesNotRecognizeSelector:(SEL aSelector)
Definition: CPObject.j:437
Used to implement exception handling (creating & raising).
Definition: CPException.h:2
id retain()
Definition: CPObject.j:573
var isEqual
function CPDescriptionOfObject(anObject, maximumRecursionDepth)
Definition: CPObject.j:603
CPString className()
Definition: CPObject.j:527
void raise:reason:(CPString aName, [reason] CPString aReason)
Definition: CPException.j:66
void release()
Definition: CPObject.j:581
void load()
Definition: CPObject.j:109
void initialize()
Definition: CPObject.j:113
CPString description()
Definition: CPObject.j:358
CPInvalidArgumentException
Definition: CPException.j:25
Class classForCoder()
Definition: CPObject.j:471
An object representation of a message.
Definition: CPInvocation.h:2
Implements keyed archiving of object graphs (e.g. for storing data).
An immutable string (collection of characters).
Definition: CPString.h:2
if(CPFeatureIsCompatible(CPHTMLCanvasFeature))
int version()
Definition: CPObject.j:518
Class classForKeyedArchiver()
Definition: CPObject.j:462
id autorelease()
Definition: CPObject.j:539
id stringWithHash:(unsigned aHash)
Definition: CPString.j:107
BOOL isSubclassOfClass:(Class aClass)
Definition: CPObject.j:204
id self()
Definition: CPObject.j:588
id copy()
Definition: CPObject.j:154
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
void dealloc()
Definition: CPObject.j:171
id init()
Definition: CPObject.j:145
BOOL isProxy()
Definition: CPObject.j:247
id replacementObjectForCoder:(CPCoder aCoder)
Definition: CPObject.j:501
Class class()
Definition: CPObject.j:179
id isa
Definition: CPObject.j:106
unsigned hash()
Definition: CPObject.j:547
Class superclass()
Definition: CPObject.j:195
CPString UID()
Definition: CPObject.j:552
id mutableCopy()
Definition: CPObject.j:163
id alloc()
Definition: CPObject.j:130
FrameUpdater prototype description