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 &lt;, ==, or &gt;.
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 +/