Mercurial > projects > ldc
comparison lphobos/internal/objectimpl.d @ 1:c53b6e3fe49a trunk
[svn r5] Initial commit. Most things are very rough.
author | lindquist |
---|---|
date | Sat, 01 Sep 2007 21:43:27 +0200 |
parents | |
children | 3cfcb944304e |
comparison
equal
deleted
inserted
replaced
0:a9e71648e74d | 1:c53b6e3fe49a |
---|---|
1 | |
2 /** | |
3 * Part of the D programming language runtime library. | |
4 * Forms the symbols available to all D programs. Includes | |
5 * Object, which is the root of the class object hierarchy. | |
6 * | |
7 * This module is implicitly imported. | |
8 * Macros: | |
9 * WIKI = Phobos/Object | |
10 */ | |
11 | |
12 /* | |
13 * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com | |
14 * Written by Walter Bright | |
15 * | |
16 * This software is provided 'as-is', without any express or implied | |
17 * warranty. In no event will the authors be held liable for any damages | |
18 * arising from the use of this software. | |
19 * | |
20 * Permission is granted to anyone to use this software for any purpose, | |
21 * including commercial applications, and to alter it and redistribute it | |
22 * freely, in both source and binary form, subject to the following | |
23 * restrictions: | |
24 * | |
25 * o The origin of this software must not be misrepresented; you must not | |
26 * claim that you wrote the original software. If you use this software | |
27 * in a product, an acknowledgment in the product documentation would be | |
28 * appreciated but is not required. | |
29 * o Altered source versions must be plainly marked as such, and must not | |
30 * be misrepresented as being the original software. | |
31 * o This notice may not be removed or altered from any source | |
32 * distribution. | |
33 */ | |
34 | |
35 | |
36 module object; | |
37 | |
38 //import std.outofmemory; | |
39 | |
40 extern (C) | |
41 { /// C's printf function. | |
42 int printf(char *, ...); | |
43 | |
44 int memcmp(void *, void *, size_t); | |
45 void* memcpy(void *, void *, size_t); | |
46 void* calloc(size_t, size_t); | |
47 void* realloc(void*, size_t); | |
48 void free(void*); | |
49 | |
50 //Object _d_newclass(ClassInfo ci); | |
51 } | |
52 | |
53 /// Standard boolean type. | |
54 alias bool bit; | |
55 | |
56 version (LLVM64) | |
57 { | |
58 /** | |
59 * An unsigned integral type large enough to span the memory space. Use for | |
60 * array indices and pointer offsets for maximal portability to | |
61 * architectures that have different memory address ranges. This is | |
62 * analogous to C's size_t. | |
63 */ | |
64 alias ulong size_t; | |
65 | |
66 /** | |
67 * A signed integral type large enough to span the memory space. Use for | |
68 * pointer differences and for size_t differences for maximal portability to | |
69 * architectures that have different memory address ranges. This is | |
70 * analogous to C's ptrdiff_t. | |
71 */ | |
72 alias long ptrdiff_t; | |
73 | |
74 alias ulong hash_t; | |
75 } | |
76 else | |
77 { | |
78 alias uint size_t; | |
79 alias int ptrdiff_t; | |
80 alias uint hash_t; | |
81 } | |
82 | |
83 /+ | |
84 /* ************************* | |
85 * Internal struct pointed to by the hidden .monitor member. | |
86 */ | |
87 struct Monitor | |
88 { | |
89 void delegate(Object)[] delegates; | |
90 | |
91 /* More stuff goes here defined by internal/monitor.c */ | |
92 } | |
93 +/ | |
94 | |
95 /****************** | |
96 * All D class objects inherit from Object. | |
97 */ | |
98 class Object | |
99 { | |
100 void print() | |
101 { | |
102 char[] s = toString(); | |
103 printf("%.*s\n", s.length, s.ptr); | |
104 } | |
105 | |
106 /** | |
107 * Convert Object to a human readable string. | |
108 */ | |
109 char[] toString() | |
110 { | |
111 //return this.classinfo.name; | |
112 return "classinfo.name not yet implemented"; | |
113 } | |
114 | |
115 /** | |
116 * Compute hash function for Object. | |
117 */ | |
118 hash_t toHash() | |
119 { | |
120 // BUG: this prevents a compacting GC from working, needs to be fixed | |
121 return cast(uint)cast(void *)this; | |
122 } | |
123 | |
124 /** | |
125 * Compare with another Object obj. | |
126 * Returns: | |
127 * $(TABLE | |
128 * $(TR $(TD this < obj) $(TD < 0)) | |
129 * $(TR $(TD this == obj) $(TD 0)) | |
130 * $(TR $(TD this > obj) $(TD > 0)) | |
131 * ) | |
132 */ | |
133 int opCmp(Object o) | |
134 { | |
135 // BUG: this prevents a compacting GC from working, needs to be fixed | |
136 //return cast(int)cast(void *)this - cast(int)cast(void *)o; | |
137 | |
138 //throw new Error("need opCmp for class " ~ this.classinfo.name); | |
139 assert(0); | |
140 return 0; | |
141 } | |
142 | |
143 /** | |
144 * Returns !=0 if this object does have the same contents as obj. | |
145 */ | |
146 int opEquals(Object o) | |
147 { | |
148 return cast(int)(this is o); | |
149 } | |
150 | |
151 /* ** | |
152 * Call delegate dg, passing this to it, when this object gets destroyed. | |
153 * Use extreme caution, as the list of delegates is stored in a place | |
154 * not known to the gc. Thus, if any objects pointed to by one of these | |
155 * delegates gets freed by the gc, calling the delegate will cause a | |
156 * crash. | |
157 * This is only for use by library developers, as it will need to be | |
158 * redone if weak pointers are added or a moving gc is developed. | |
159 */ | |
160 final void notifyRegister(void delegate(Object) dg) | |
161 { | |
162 //printf("notifyRegister(dg = %llx, o = %p)\n", dg, this); | |
163 /+synchronized (this) | |
164 { | |
165 Monitor* m = cast(Monitor*)(cast(void**)this)[1]; | |
166 foreach (inout x; m.delegates) | |
167 { | |
168 if (!x || x == dg) | |
169 { x = dg; | |
170 return; | |
171 } | |
172 } | |
173 | |
174 // Increase size of delegates[] | |
175 auto len = m.delegates.length; | |
176 auto startlen = len; | |
177 if (len == 0) | |
178 { | |
179 len = 4; | |
180 auto p = calloc((void delegate(Object)).sizeof, len); | |
181 if (!p) | |
182 _d_OutOfMemory(); | |
183 m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; | |
184 } | |
185 else | |
186 { | |
187 len += len + 4; | |
188 auto p = realloc(m.delegates.ptr, (void delegate(Object)).sizeof * len); | |
189 if (!p) | |
190 _d_OutOfMemory(); | |
191 m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; | |
192 m.delegates[startlen .. len] = null; | |
193 } | |
194 m.delegates[startlen] = dg; | |
195 }+/ | |
196 } | |
197 | |
198 /* ** | |
199 * Remove delegate dg from the notify list. | |
200 * This is only for use by library developers, as it will need to be | |
201 * redone if weak pointers are added or a moving gc is developed. | |
202 */ | |
203 final void notifyUnRegister(void delegate(Object) dg) | |
204 { | |
205 /+synchronized (this) | |
206 { | |
207 Monitor* m = cast(Monitor*)(cast(void**)this)[1]; | |
208 foreach (inout x; m.delegates) | |
209 { | |
210 if (x == dg) | |
211 x = null; | |
212 } | |
213 }+/ | |
214 } | |
215 | |
216 /****** | |
217 * Create instance of class specified by classname. | |
218 * The class must either have no constructors or have | |
219 * a default constructor. | |
220 * Returns: | |
221 * null if failed | |
222 */ | |
223 static Object factory(char[] classname) | |
224 { | |
225 /+auto ci = ClassInfo.find(classname); | |
226 if (ci) | |
227 { | |
228 return ci.create(); | |
229 }+/ | |
230 return null; | |
231 } | |
232 } | |
233 | |
234 /+ | |
235 extern (C) void _d_notify_release(Object o) | |
236 { | |
237 //printf("_d_notify_release(o = %p)\n", o); | |
238 Monitor* m = cast(Monitor*)(cast(void**)o)[1]; | |
239 if (m.delegates.length) | |
240 { | |
241 auto dgs = m.delegates; | |
242 synchronized (o) | |
243 { | |
244 dgs = m.delegates; | |
245 m.delegates = null; | |
246 } | |
247 | |
248 foreach (dg; dgs) | |
249 { | |
250 if (dg) | |
251 { //printf("calling dg = %llx (%p)\n", dg, o); | |
252 dg(o); | |
253 } | |
254 } | |
255 | |
256 free(dgs.ptr); | |
257 } | |
258 } | |
259 | |
260 | |
261 /** | |
262 * Information about an interface. | |
263 * A pointer to this appears as the first entry in the interface's vtbl[]. | |
264 */ | |
265 struct Interface | |
266 { | |
267 ClassInfo classinfo; /// .classinfo for this interface (not for containing class) | |
268 void *[] vtbl; | |
269 int offset; /// offset to Interface 'this' from Object 'this' | |
270 } | |
271 | |
272 import std.moduleinit; | |
273 /** | |
274 * Runtime type information about a class. Can be retrieved for any class type | |
275 * or instance by using the .classinfo property. | |
276 * A pointer to this appears as the first entry in the class's vtbl[]. | |
277 */ | |
278 class ClassInfo : Object | |
279 { | |
280 byte[] init; /** class static initializer | |
281 * (init.length gives size in bytes of class) | |
282 */ | |
283 char[] name; /// class name | |
284 void *[] vtbl; /// virtual function pointer table | |
285 Interface[] interfaces; /// interfaces this class implements | |
286 ClassInfo base; /// base class | |
287 void *destructor; | |
288 void (*classInvariant)(Object); | |
289 uint flags; | |
290 // 1: // IUnknown | |
291 // 2: // has no possible pointers into GC memory | |
292 // 4: // has offTi[] member | |
293 // 8: // has constructors | |
294 void *deallocator; | |
295 OffsetTypeInfo[] offTi; | |
296 void function(Object) defaultConstructor; // default Constructor | |
297 | |
298 /************* | |
299 * Search all modules for ClassInfo corresponding to classname. | |
300 * Returns: null if not found | |
301 */ | |
302 static ClassInfo find(char[] classname) | |
303 { | |
304 foreach (m; ModuleInfo.modules()) | |
305 { | |
306 //writefln("module %s, %d", m.name, m.localClasses.length); | |
307 foreach (c; m.localClasses) | |
308 { | |
309 //writefln("\tclass %s", c.name); | |
310 if (c.name == classname) | |
311 return c; | |
312 } | |
313 } | |
314 return null; | |
315 } | |
316 | |
317 /******************** | |
318 * Create instance of Object represented by 'this'. | |
319 */ | |
320 Object create() | |
321 { | |
322 if (flags & 8 && !defaultConstructor) | |
323 return null; | |
324 Object o = _d_newclass(this); | |
325 if (flags & 8 && defaultConstructor) | |
326 { | |
327 defaultConstructor(o); | |
328 } | |
329 return o; | |
330 } | |
331 } | |
332 | |
333 private import std.string; | |
334 | |
335 /** | |
336 * Array of pairs giving the offset and type information for each | |
337 * member in an aggregate. | |
338 */ | |
339 struct OffsetTypeInfo | |
340 { | |
341 size_t offset; /// Offset of member from start of object | |
342 TypeInfo ti; /// TypeInfo for this member | |
343 } | |
344 | |
345 | |
346 /** | |
347 * Runtime type information about a type. | |
348 * Can be retrieved for any type using a | |
349 * <a href="../expression.html#typeidexpression">TypeidExpression</a>. | |
350 */ | |
351 class TypeInfo | |
352 { | |
353 hash_t toHash() | |
354 { hash_t hash; | |
355 | |
356 foreach (char c; this.toString()) | |
357 hash = hash * 9 + c; | |
358 return hash; | |
359 } | |
360 | |
361 int opCmp(Object o) | |
362 { | |
363 if (this is o) | |
364 return 0; | |
365 TypeInfo ti = cast(TypeInfo)o; | |
366 if (ti is null) | |
367 return 1; | |
368 return std.string.cmp(this.toString(), ti.toString()); | |
369 } | |
370 | |
371 int opEquals(Object o) | |
372 { | |
373 /* TypeInfo instances are singletons, but duplicates can exist | |
374 * across DLL's. Therefore, comparing for a name match is | |
375 * sufficient. | |
376 */ | |
377 if (this is o) | |
378 return 1; | |
379 TypeInfo ti = cast(TypeInfo)o; | |
380 return cast(int)(ti && this.toString() == ti.toString()); | |
381 } | |
382 | |
383 /// Returns a hash of the instance of a type. | |
384 hash_t getHash(void *p) { return cast(uint)p; } | |
385 | |
386 /// Compares two instances for equality. | |
387 int equals(void *p1, void *p2) { return cast(int)(p1 == p2); } | |
388 | |
389 /// Compares two instances for <, ==, or >. | |
390 int compare(void *p1, void *p2) { return 0; } | |
391 | |
392 /// Returns size of the type. | |
393 size_t tsize() { return 0; } | |
394 | |
395 /// Swaps two instances of the type. | |
396 void swap(void *p1, void *p2) | |
397 { | |
398 size_t n = tsize(); | |
399 for (size_t i = 0; i < n; i++) | |
400 { byte t; | |
401 | |
402 t = (cast(byte *)p1)[i]; | |
403 (cast(byte *)p1)[i] = (cast(byte *)p2)[i]; | |
404 (cast(byte *)p2)[i] = t; | |
405 } | |
406 } | |
407 | |
408 /// Get TypeInfo for 'next' type, as defined by what kind of type this is, | |
409 /// null if none. | |
410 TypeInfo next() { return null; } | |
411 | |
412 /// Return default initializer, null if default initialize to 0 | |
413 void[] init() { return null; } | |
414 | |
415 /// Get flags for type: 1 means GC should scan for pointers | |
416 uint flags() { return 0; } | |
417 | |
418 /// Get type information on the contents of the type; null if not available | |
419 OffsetTypeInfo[] offTi() { return null; } | |
420 } | |
421 | |
422 class TypeInfo_Typedef : TypeInfo | |
423 { | |
424 char[] toString() { return name; } | |
425 | |
426 int opEquals(Object o) | |
427 { TypeInfo_Typedef c; | |
428 | |
429 return cast(int) | |
430 (this is o || | |
431 ((c = cast(TypeInfo_Typedef)o) !is null && | |
432 this.name == c.name && | |
433 this.base == c.base)); | |
434 } | |
435 | |
436 hash_t getHash(void *p) { return base.getHash(p); } | |
437 int equals(void *p1, void *p2) { return base.equals(p1, p2); } | |
438 int compare(void *p1, void *p2) { return base.compare(p1, p2); } | |
439 size_t tsize() { return base.tsize(); } | |
440 void swap(void *p1, void *p2) { return base.swap(p1, p2); } | |
441 | |
442 TypeInfo next() { return base.next(); } | |
443 uint flags() { return base.flags(); } | |
444 void[] init() { return m_init.length ? m_init : base.init(); } | |
445 | |
446 TypeInfo base; | |
447 char[] name; | |
448 void[] m_init; | |
449 } | |
450 | |
451 class TypeInfo_Enum : TypeInfo_Typedef | |
452 { | |
453 } | |
454 | |
455 class TypeInfo_Pointer : TypeInfo | |
456 { | |
457 char[] toString() { return m_next.toString() ~ "*"; } | |
458 | |
459 int opEquals(Object o) | |
460 { TypeInfo_Pointer c; | |
461 | |
462 return this is o || | |
463 ((c = cast(TypeInfo_Pointer)o) !is null && | |
464 this.m_next == c.m_next); | |
465 } | |
466 | |
467 hash_t getHash(void *p) | |
468 { | |
469 return cast(uint)*cast(void* *)p; | |
470 } | |
471 | |
472 int equals(void *p1, void *p2) | |
473 { | |
474 return cast(int)(*cast(void* *)p1 == *cast(void* *)p2); | |
475 } | |
476 | |
477 int compare(void *p1, void *p2) | |
478 { | |
479 if (*cast(void* *)p1 < *cast(void* *)p2) | |
480 return -1; | |
481 else if (*cast(void* *)p1 > *cast(void* *)p2) | |
482 return 1; | |
483 else | |
484 return 0; | |
485 } | |
486 | |
487 size_t tsize() | |
488 { | |
489 return (void*).sizeof; | |
490 } | |
491 | |
492 void swap(void *p1, void *p2) | |
493 { void* tmp; | |
494 tmp = *cast(void**)p1; | |
495 *cast(void**)p1 = *cast(void**)p2; | |
496 *cast(void**)p2 = tmp; | |
497 } | |
498 | |
499 TypeInfo next() { return m_next; } | |
500 uint flags() { return 1; } | |
501 | |
502 TypeInfo m_next; | |
503 } | |
504 | |
505 class TypeInfo_Array : TypeInfo | |
506 { | |
507 char[] toString() { return value.toString() ~ "[]"; } | |
508 | |
509 int opEquals(Object o) | |
510 { TypeInfo_Array c; | |
511 | |
512 return cast(int) | |
513 (this is o || | |
514 ((c = cast(TypeInfo_Array)o) !is null && | |
515 this.value == c.value)); | |
516 } | |
517 | |
518 hash_t getHash(void *p) | |
519 { size_t sz = value.tsize(); | |
520 hash_t hash = 0; | |
521 void[] a = *cast(void[]*)p; | |
522 for (size_t i = 0; i < a.length; i++) | |
523 hash += value.getHash(a.ptr + i * sz); | |
524 return hash; | |
525 } | |
526 | |
527 int equals(void *p1, void *p2) | |
528 { | |
529 void[] a1 = *cast(void[]*)p1; | |
530 void[] a2 = *cast(void[]*)p2; | |
531 if (a1.length != a2.length) | |
532 return 0; | |
533 size_t sz = value.tsize(); | |
534 for (size_t i = 0; i < a1.length; i++) | |
535 { | |
536 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) | |
537 return 0; | |
538 } | |
539 return 1; | |
540 } | |
541 | |
542 int compare(void *p1, void *p2) | |
543 { | |
544 void[] a1 = *cast(void[]*)p1; | |
545 void[] a2 = *cast(void[]*)p2; | |
546 size_t sz = value.tsize(); | |
547 size_t len = a1.length; | |
548 | |
549 if (a2.length < len) | |
550 len = a2.length; | |
551 for (size_t u = 0; u < len; u++) | |
552 { | |
553 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); | |
554 if (result) | |
555 return result; | |
556 } | |
557 return cast(int)a1.length - cast(int)a2.length; | |
558 } | |
559 | |
560 size_t tsize() | |
561 { | |
562 return (void[]).sizeof; | |
563 } | |
564 | |
565 void swap(void *p1, void *p2) | |
566 { void[] tmp; | |
567 tmp = *cast(void[]*)p1; | |
568 *cast(void[]*)p1 = *cast(void[]*)p2; | |
569 *cast(void[]*)p2 = tmp; | |
570 } | |
571 | |
572 TypeInfo value; | |
573 | |
574 TypeInfo next() | |
575 { | |
576 return value; | |
577 } | |
578 | |
579 uint flags() { return 1; } | |
580 } | |
581 | |
582 class TypeInfo_StaticArray : TypeInfo | |
583 { | |
584 char[] toString() | |
585 { | |
586 return value.toString() ~ "[" ~ std.string.toString(len) ~ "]"; | |
587 } | |
588 | |
589 int opEquals(Object o) | |
590 { TypeInfo_StaticArray c; | |
591 | |
592 return cast(int) | |
593 (this is o || | |
594 ((c = cast(TypeInfo_StaticArray)o) !is null && | |
595 this.len == c.len && | |
596 this.value == c.value)); | |
597 } | |
598 | |
599 hash_t getHash(void *p) | |
600 { size_t sz = value.tsize(); | |
601 hash_t hash = 0; | |
602 for (size_t i = 0; i < len; i++) | |
603 hash += value.getHash(p + i * sz); | |
604 return hash; | |
605 } | |
606 | |
607 int equals(void *p1, void *p2) | |
608 { | |
609 size_t sz = value.tsize(); | |
610 | |
611 for (size_t u = 0; u < len; u++) | |
612 { | |
613 if (!value.equals(p1 + u * sz, p2 + u * sz)) | |
614 return 0; | |
615 } | |
616 return 1; | |
617 } | |
618 | |
619 int compare(void *p1, void *p2) | |
620 { | |
621 size_t sz = value.tsize(); | |
622 | |
623 for (size_t u = 0; u < len; u++) | |
624 { | |
625 int result = value.compare(p1 + u * sz, p2 + u * sz); | |
626 if (result) | |
627 return result; | |
628 } | |
629 return 0; | |
630 } | |
631 | |
632 size_t tsize() | |
633 { | |
634 return len * value.tsize(); | |
635 } | |
636 | |
637 void swap(void *p1, void *p2) | |
638 { void* tmp; | |
639 size_t sz = value.tsize(); | |
640 ubyte[16] buffer; | |
641 void* pbuffer; | |
642 | |
643 if (sz < buffer.sizeof) | |
644 tmp = buffer.ptr; | |
645 else | |
646 tmp = pbuffer = (new void[sz]).ptr; | |
647 | |
648 for (size_t u = 0; u < len; u += sz) | |
649 { size_t o = u * sz; | |
650 memcpy(tmp, p1 + o, sz); | |
651 memcpy(p1 + o, p2 + o, sz); | |
652 memcpy(p2 + o, tmp, sz); | |
653 } | |
654 if (pbuffer) | |
655 delete pbuffer; | |
656 } | |
657 | |
658 void[] init() { return value.init(); } | |
659 TypeInfo next() { return value; } | |
660 uint flags() { return value.flags(); } | |
661 | |
662 TypeInfo value; | |
663 size_t len; | |
664 } | |
665 | |
666 class TypeInfo_AssociativeArray : TypeInfo | |
667 { | |
668 char[] toString() | |
669 { | |
670 return value.toString() ~ "[" ~ key.toString() ~ "]"; | |
671 } | |
672 | |
673 int opEquals(Object o) | |
674 { TypeInfo_AssociativeArray c; | |
675 | |
676 return this is o || | |
677 ((c = cast(TypeInfo_AssociativeArray)o) !is null && | |
678 this.key == c.key && | |
679 this.value == c.value); | |
680 } | |
681 | |
682 // BUG: need to add the rest of the functions | |
683 | |
684 size_t tsize() | |
685 { | |
686 return (char[int]).sizeof; | |
687 } | |
688 | |
689 TypeInfo next() { return value; } | |
690 uint flags() { return 1; } | |
691 | |
692 TypeInfo value; | |
693 TypeInfo key; | |
694 } | |
695 | |
696 class TypeInfo_Function : TypeInfo | |
697 { | |
698 char[] toString() | |
699 { | |
700 return next.toString() ~ "()"; | |
701 } | |
702 | |
703 int opEquals(Object o) | |
704 { TypeInfo_Function c; | |
705 | |
706 return this is o || | |
707 ((c = cast(TypeInfo_Function)o) !is null && | |
708 this.next == c.next); | |
709 } | |
710 | |
711 // BUG: need to add the rest of the functions | |
712 | |
713 size_t tsize() | |
714 { | |
715 return 0; // no size for functions | |
716 } | |
717 | |
718 TypeInfo next; | |
719 } | |
720 | |
721 class TypeInfo_Delegate : TypeInfo | |
722 { | |
723 char[] toString() | |
724 { | |
725 return next.toString() ~ " delegate()"; | |
726 } | |
727 | |
728 int opEquals(Object o) | |
729 { TypeInfo_Delegate c; | |
730 | |
731 return this is o || | |
732 ((c = cast(TypeInfo_Delegate)o) !is null && | |
733 this.next == c.next); | |
734 } | |
735 | |
736 // BUG: need to add the rest of the functions | |
737 | |
738 size_t tsize() | |
739 { alias int delegate() dg; | |
740 return dg.sizeof; | |
741 } | |
742 | |
743 uint flags() { return 1; } | |
744 | |
745 TypeInfo next; | |
746 } | |
747 | |
748 class TypeInfo_Class : TypeInfo | |
749 { | |
750 char[] toString() { return info.name; } | |
751 | |
752 int opEquals(Object o) | |
753 { TypeInfo_Class c; | |
754 | |
755 return this is o || | |
756 ((c = cast(TypeInfo_Class)o) !is null && | |
757 this.info.name == c.classinfo.name); | |
758 } | |
759 | |
760 hash_t getHash(void *p) | |
761 { | |
762 Object o = *cast(Object*)p; | |
763 assert(o); | |
764 return o.toHash(); | |
765 } | |
766 | |
767 int equals(void *p1, void *p2) | |
768 { | |
769 Object o1 = *cast(Object*)p1; | |
770 Object o2 = *cast(Object*)p2; | |
771 | |
772 return (o1 is o2) || (o1 && o1.opEquals(o2)); | |
773 } | |
774 | |
775 int compare(void *p1, void *p2) | |
776 { | |
777 Object o1 = *cast(Object*)p1; | |
778 Object o2 = *cast(Object*)p2; | |
779 int c = 0; | |
780 | |
781 // Regard null references as always being "less than" | |
782 if (o1 !is o2) | |
783 { | |
784 if (o1) | |
785 { if (!o2) | |
786 c = 1; | |
787 else | |
788 c = o1.opCmp(o2); | |
789 } | |
790 else | |
791 c = -1; | |
792 } | |
793 return c; | |
794 } | |
795 | |
796 size_t tsize() | |
797 { | |
798 return Object.sizeof; | |
799 } | |
800 | |
801 uint flags() { return 1; } | |
802 | |
803 OffsetTypeInfo[] offTi() | |
804 { | |
805 return (info.flags & 4) ? info.offTi : null; | |
806 } | |
807 | |
808 ClassInfo info; | |
809 } | |
810 | |
811 class TypeInfo_Interface : TypeInfo | |
812 { | |
813 char[] toString() { return info.name; } | |
814 | |
815 int opEquals(Object o) | |
816 { TypeInfo_Interface c; | |
817 | |
818 return this is o || | |
819 ((c = cast(TypeInfo_Interface)o) !is null && | |
820 this.info.name == c.classinfo.name); | |
821 } | |
822 | |
823 hash_t getHash(void *p) | |
824 { | |
825 Interface* pi = **cast(Interface ***)*cast(void**)p; | |
826 Object o = cast(Object)(*cast(void**)p - pi.offset); | |
827 assert(o); | |
828 return o.toHash(); | |
829 } | |
830 | |
831 int equals(void *p1, void *p2) | |
832 { | |
833 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
834 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
835 pi = **cast(Interface ***)*cast(void**)p2; | |
836 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
837 | |
838 return o1 == o2 || (o1 && o1.opCmp(o2) == 0); | |
839 } | |
840 | |
841 int compare(void *p1, void *p2) | |
842 { | |
843 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
844 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
845 pi = **cast(Interface ***)*cast(void**)p2; | |
846 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
847 int c = 0; | |
848 | |
849 // Regard null references as always being "less than" | |
850 if (o1 != o2) | |
851 { | |
852 if (o1) | |
853 { if (!o2) | |
854 c = 1; | |
855 else | |
856 c = o1.opCmp(o2); | |
857 } | |
858 else | |
859 c = -1; | |
860 } | |
861 return c; | |
862 } | |
863 | |
864 size_t tsize() | |
865 { | |
866 return Object.sizeof; | |
867 } | |
868 | |
869 uint flags() { return 1; } | |
870 | |
871 ClassInfo info; | |
872 } | |
873 | |
874 class TypeInfo_Struct : TypeInfo | |
875 { | |
876 char[] toString() { return name; } | |
877 | |
878 int opEquals(Object o) | |
879 { TypeInfo_Struct s; | |
880 | |
881 return this is o || | |
882 ((s = cast(TypeInfo_Struct)o) !is null && | |
883 this.name == s.name && | |
884 this.init.length == s.init.length); | |
885 } | |
886 | |
887 hash_t getHash(void *p) | |
888 { hash_t h; | |
889 | |
890 assert(p); | |
891 if (xtoHash) | |
892 { //printf("getHash() using xtoHash\n"); | |
893 h = (*xtoHash)(p); | |
894 } | |
895 else | |
896 { | |
897 //printf("getHash() using default hash\n"); | |
898 // A sorry hash algorithm. | |
899 // Should use the one for strings. | |
900 // BUG: relies on the GC not moving objects | |
901 for (size_t i = 0; i < init.length; i++) | |
902 { h = h * 9 + *cast(ubyte*)p; | |
903 p++; | |
904 } | |
905 } | |
906 return h; | |
907 } | |
908 | |
909 int equals(void *p2, void *p1) | |
910 { int c; | |
911 | |
912 if (p1 == p2) | |
913 c = 1; | |
914 else if (!p1 || !p2) | |
915 c = 0; | |
916 else if (xopEquals) | |
917 c = (*xopEquals)(p1, p2); | |
918 else | |
919 // BUG: relies on the GC not moving objects | |
920 c = (memcmp(p1, p2, init.length) == 0); | |
921 return c; | |
922 } | |
923 | |
924 int compare(void *p2, void *p1) | |
925 { | |
926 int c = 0; | |
927 | |
928 // Regard null references as always being "less than" | |
929 if (p1 != p2) | |
930 { | |
931 if (p1) | |
932 { if (!p2) | |
933 c = 1; | |
934 else if (xopCmp) | |
935 c = (*xopCmp)(p1, p2); | |
936 else | |
937 // BUG: relies on the GC not moving objects | |
938 c = memcmp(p1, p2, init.length); | |
939 } | |
940 else | |
941 c = -1; | |
942 } | |
943 return c; | |
944 } | |
945 | |
946 size_t tsize() | |
947 { | |
948 return init.length; | |
949 } | |
950 | |
951 void[] init() { return m_init; } | |
952 | |
953 uint flags() { return m_flags; } | |
954 | |
955 char[] name; | |
956 void[] m_init; // initializer; init.ptr == null if 0 initialize | |
957 | |
958 hash_t function(void*) xtoHash; | |
959 int function(void*,void*) xopEquals; | |
960 int function(void*,void*) xopCmp; | |
961 char[] function(void*) xtoString; | |
962 | |
963 uint m_flags; | |
964 } | |
965 | |
966 class TypeInfo_Tuple : TypeInfo | |
967 { | |
968 TypeInfo[] elements; | |
969 | |
970 char[] toString() | |
971 { | |
972 char[] s; | |
973 s = "("; | |
974 foreach (i, element; elements) | |
975 { | |
976 if (i) | |
977 s ~= ','; | |
978 s ~= element.toString(); | |
979 } | |
980 s ~= ")"; | |
981 return s; | |
982 } | |
983 | |
984 int opEquals(Object o) | |
985 { | |
986 if (this is o) | |
987 return 1; | |
988 | |
989 auto t = cast(TypeInfo_Tuple)o; | |
990 if (t && elements.length == t.elements.length) | |
991 { | |
992 for (size_t i = 0; i < elements.length; i++) | |
993 { | |
994 if (elements[i] != t.elements[i]) | |
995 return 0; | |
996 } | |
997 return 1; | |
998 } | |
999 return 0; | |
1000 } | |
1001 | |
1002 hash_t getHash(void *p) | |
1003 { | |
1004 assert(0); | |
1005 } | |
1006 | |
1007 int equals(void *p1, void *p2) | |
1008 { | |
1009 assert(0); | |
1010 } | |
1011 | |
1012 int compare(void *p1, void *p2) | |
1013 { | |
1014 assert(0); | |
1015 } | |
1016 | |
1017 size_t tsize() | |
1018 { | |
1019 assert(0); | |
1020 } | |
1021 | |
1022 void swap(void *p1, void *p2) | |
1023 { | |
1024 assert(0); | |
1025 } | |
1026 } | |
1027 | |
1028 /** | |
1029 * All recoverable exceptions should be derived from class Exception. | |
1030 */ | |
1031 class Exception : Object | |
1032 { | |
1033 char[] msg; | |
1034 | |
1035 /** | |
1036 * Constructor; msg is a descriptive message for the exception. | |
1037 */ | |
1038 this(char[] msg) | |
1039 { | |
1040 this.msg = msg; | |
1041 } | |
1042 | |
1043 void print() | |
1044 { | |
1045 printf("%.*s\n", toString()); | |
1046 } | |
1047 | |
1048 char[] toString() { return msg; } | |
1049 } | |
1050 | |
1051 /** | |
1052 * All irrecoverable exceptions should be derived from class Error. | |
1053 */ | |
1054 class Error : Exception | |
1055 { | |
1056 Error next; | |
1057 | |
1058 /** | |
1059 * Constructor; msg is a descriptive message for the exception. | |
1060 */ | |
1061 this(char[] msg) | |
1062 { | |
1063 super(msg); | |
1064 } | |
1065 | |
1066 this(char[] msg, Error next) | |
1067 { | |
1068 super(msg); | |
1069 this.next = next; | |
1070 } | |
1071 } | |
1072 | |
1073 //extern (C) int nullext = 0; | |
1074 | |
1075 +/ |