Mercurial > projects > ldc
annotate lphobos/internal/objectimpl.d @ 35:3cfcb944304e trunk
[svn r39] * Updated to DMD 1.022 with the exception of:
Bugzilla 278: dmd.conf search path doesn't work
This fix was causing crashes for me :/ So for it's the old behaviour
author | lindquist |
---|---|
date | Tue, 09 Oct 2007 06:21:30 +0200 |
parents | c53b6e3fe49a |
children | 0b9b286b67b6 |
rev | line source |
---|---|
1 | 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; | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
112 return "Object.toString: classinfo not yet implemented"; |
1 | 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 | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
138 assert(0, "need opCmp for class <no classinfo yet>"); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
139 return 0; |
1 | 140 //throw new Error("need opCmp for class " ~ this.classinfo.name); |
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 * Information about an interface. | |
262 * A pointer to this appears as the first entry in the interface's vtbl[]. | |
263 */ | |
264 struct Interface | |
265 { | |
266 ClassInfo classinfo; /// .classinfo for this interface (not for containing class) | |
267 void *[] vtbl; | |
268 int offset; /// offset to Interface 'this' from Object 'this' | |
269 } | |
270 | |
271 import std.moduleinit; | |
272 /** | |
273 * Runtime type information about a class. Can be retrieved for any class type | |
274 * or instance by using the .classinfo property. | |
275 * A pointer to this appears as the first entry in the class's vtbl[]. | |
276 */ | |
277 class ClassInfo : Object | |
278 { | |
279 byte[] init; /** class static initializer | |
280 * (init.length gives size in bytes of class) | |
281 */ | |
282 char[] name; /// class name | |
283 void *[] vtbl; /// virtual function pointer table | |
284 Interface[] interfaces; /// interfaces this class implements | |
285 ClassInfo base; /// base class | |
286 void *destructor; | |
287 void (*classInvariant)(Object); | |
288 uint flags; | |
289 // 1: // IUnknown | |
290 // 2: // has no possible pointers into GC memory | |
291 // 4: // has offTi[] member | |
292 // 8: // has constructors | |
293 void *deallocator; | |
294 OffsetTypeInfo[] offTi; | |
295 void function(Object) defaultConstructor; // default Constructor | |
296 | |
297 /************* | |
298 * Search all modules for ClassInfo corresponding to classname. | |
299 * Returns: null if not found | |
300 */ | |
301 static ClassInfo find(char[] classname) | |
302 { | |
303 foreach (m; ModuleInfo.modules()) | |
304 { | |
305 //writefln("module %s, %d", m.name, m.localClasses.length); | |
306 foreach (c; m.localClasses) | |
307 { | |
308 //writefln("\tclass %s", c.name); | |
309 if (c.name == classname) | |
310 return c; | |
311 } | |
312 } | |
313 return null; | |
314 } | |
315 | |
316 /******************** | |
317 * Create instance of Object represented by 'this'. | |
318 */ | |
319 Object create() | |
320 { | |
321 if (flags & 8 && !defaultConstructor) | |
322 return null; | |
323 Object o = _d_newclass(this); | |
324 if (flags & 8 && defaultConstructor) | |
325 { | |
326 defaultConstructor(o); | |
327 } | |
328 return o; | |
329 } | |
330 } | |
331 | |
332 private import std.string; | |
333 | |
334 /** | |
335 * Array of pairs giving the offset and type information for each | |
336 * member in an aggregate. | |
337 */ | |
338 struct OffsetTypeInfo | |
339 { | |
340 size_t offset; /// Offset of member from start of object | |
341 TypeInfo ti; /// TypeInfo for this member | |
342 } | |
343 | |
344 /** | |
345 * Runtime type information about a type. | |
346 * Can be retrieved for any type using a | |
347 * <a href="../expression.html#typeidexpression">TypeidExpression</a>. | |
348 */ | |
349 class TypeInfo | |
350 { | |
351 hash_t toHash() | |
352 { hash_t hash; | |
353 | |
354 foreach (char c; this.toString()) | |
355 hash = hash * 9 + c; | |
356 return hash; | |
357 } | |
358 | |
359 int opCmp(Object o) | |
360 { | |
361 if (this is o) | |
362 return 0; | |
363 TypeInfo ti = cast(TypeInfo)o; | |
364 if (ti is null) | |
365 return 1; | |
366 return std.string.cmp(this.toString(), ti.toString()); | |
367 } | |
368 | |
369 int opEquals(Object o) | |
370 { | |
371 /* TypeInfo instances are singletons, but duplicates can exist | |
372 * across DLL's. Therefore, comparing for a name match is | |
373 * sufficient. | |
374 */ | |
375 if (this is o) | |
376 return 1; | |
377 TypeInfo ti = cast(TypeInfo)o; | |
378 return cast(int)(ti && this.toString() == ti.toString()); | |
379 } | |
380 | |
381 /// Returns a hash of the instance of a type. | |
382 hash_t getHash(void *p) { return cast(uint)p; } | |
383 | |
384 /// Compares two instances for equality. | |
385 int equals(void *p1, void *p2) { return cast(int)(p1 == p2); } | |
386 | |
387 /// Compares two instances for <, ==, or >. | |
388 int compare(void *p1, void *p2) { return 0; } | |
389 | |
390 /// Returns size of the type. | |
391 size_t tsize() { return 0; } | |
392 | |
393 /// Swaps two instances of the type. | |
394 void swap(void *p1, void *p2) | |
395 { | |
396 size_t n = tsize(); | |
397 for (size_t i = 0; i < n; i++) | |
398 { byte t; | |
399 | |
400 t = (cast(byte *)p1)[i]; | |
401 (cast(byte *)p1)[i] = (cast(byte *)p2)[i]; | |
402 (cast(byte *)p2)[i] = t; | |
403 } | |
404 } | |
405 | |
406 /// Get TypeInfo for 'next' type, as defined by what kind of type this is, | |
407 /// null if none. | |
408 TypeInfo next() { return null; } | |
409 | |
410 /// Return default initializer, null if default initialize to 0 | |
411 void[] init() { return null; } | |
412 | |
413 /// Get flags for type: 1 means GC should scan for pointers | |
414 uint flags() { return 0; } | |
415 | |
416 /// Get type information on the contents of the type; null if not available | |
417 OffsetTypeInfo[] offTi() { return null; } | |
418 } | |
419 | |
420 class TypeInfo_Typedef : TypeInfo | |
421 { | |
422 char[] toString() { return name; } | |
423 | |
424 int opEquals(Object o) | |
425 { TypeInfo_Typedef c; | |
426 | |
427 return cast(int) | |
428 (this is o || | |
429 ((c = cast(TypeInfo_Typedef)o) !is null && | |
430 this.name == c.name && | |
431 this.base == c.base)); | |
432 } | |
433 | |
434 hash_t getHash(void *p) { return base.getHash(p); } | |
435 int equals(void *p1, void *p2) { return base.equals(p1, p2); } | |
436 int compare(void *p1, void *p2) { return base.compare(p1, p2); } | |
437 size_t tsize() { return base.tsize(); } | |
438 void swap(void *p1, void *p2) { return base.swap(p1, p2); } | |
439 | |
440 TypeInfo next() { return base.next(); } | |
441 uint flags() { return base.flags(); } | |
442 void[] init() { return m_init.length ? m_init : base.init(); } | |
443 | |
444 TypeInfo base; | |
445 char[] name; | |
446 void[] m_init; | |
447 } | |
448 | |
449 class TypeInfo_Enum : TypeInfo_Typedef | |
450 { | |
451 } | |
452 | |
453 class TypeInfo_Pointer : TypeInfo | |
454 { | |
455 char[] toString() { return m_next.toString() ~ "*"; } | |
456 | |
457 int opEquals(Object o) | |
458 { TypeInfo_Pointer c; | |
459 | |
460 return this is o || | |
461 ((c = cast(TypeInfo_Pointer)o) !is null && | |
462 this.m_next == c.m_next); | |
463 } | |
464 | |
465 hash_t getHash(void *p) | |
466 { | |
467 return cast(uint)*cast(void* *)p; | |
468 } | |
469 | |
470 int equals(void *p1, void *p2) | |
471 { | |
472 return cast(int)(*cast(void* *)p1 == *cast(void* *)p2); | |
473 } | |
474 | |
475 int compare(void *p1, void *p2) | |
476 { | |
477 if (*cast(void* *)p1 < *cast(void* *)p2) | |
478 return -1; | |
479 else if (*cast(void* *)p1 > *cast(void* *)p2) | |
480 return 1; | |
481 else | |
482 return 0; | |
483 } | |
484 | |
485 size_t tsize() | |
486 { | |
487 return (void*).sizeof; | |
488 } | |
489 | |
490 void swap(void *p1, void *p2) | |
491 { void* tmp; | |
492 tmp = *cast(void**)p1; | |
493 *cast(void**)p1 = *cast(void**)p2; | |
494 *cast(void**)p2 = tmp; | |
495 } | |
496 | |
497 TypeInfo next() { return m_next; } | |
498 uint flags() { return 1; } | |
499 | |
500 TypeInfo m_next; | |
501 } | |
502 | |
503 class TypeInfo_Array : TypeInfo | |
504 { | |
505 char[] toString() { return value.toString() ~ "[]"; } | |
506 | |
507 int opEquals(Object o) | |
508 { TypeInfo_Array c; | |
509 | |
510 return cast(int) | |
511 (this is o || | |
512 ((c = cast(TypeInfo_Array)o) !is null && | |
513 this.value == c.value)); | |
514 } | |
515 | |
516 hash_t getHash(void *p) | |
517 { size_t sz = value.tsize(); | |
518 hash_t hash = 0; | |
519 void[] a = *cast(void[]*)p; | |
520 for (size_t i = 0; i < a.length; i++) | |
521 hash += value.getHash(a.ptr + i * sz); | |
522 return hash; | |
523 } | |
524 | |
525 int equals(void *p1, void *p2) | |
526 { | |
527 void[] a1 = *cast(void[]*)p1; | |
528 void[] a2 = *cast(void[]*)p2; | |
529 if (a1.length != a2.length) | |
530 return 0; | |
531 size_t sz = value.tsize(); | |
532 for (size_t i = 0; i < a1.length; i++) | |
533 { | |
534 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) | |
535 return 0; | |
536 } | |
537 return 1; | |
538 } | |
539 | |
540 int compare(void *p1, void *p2) | |
541 { | |
542 void[] a1 = *cast(void[]*)p1; | |
543 void[] a2 = *cast(void[]*)p2; | |
544 size_t sz = value.tsize(); | |
545 size_t len = a1.length; | |
546 | |
547 if (a2.length < len) | |
548 len = a2.length; | |
549 for (size_t u = 0; u < len; u++) | |
550 { | |
551 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); | |
552 if (result) | |
553 return result; | |
554 } | |
555 return cast(int)a1.length - cast(int)a2.length; | |
556 } | |
557 | |
558 size_t tsize() | |
559 { | |
560 return (void[]).sizeof; | |
561 } | |
562 | |
563 void swap(void *p1, void *p2) | |
564 { void[] tmp; | |
565 tmp = *cast(void[]*)p1; | |
566 *cast(void[]*)p1 = *cast(void[]*)p2; | |
567 *cast(void[]*)p2 = tmp; | |
568 } | |
569 | |
570 TypeInfo value; | |
571 | |
572 TypeInfo next() | |
573 { | |
574 return value; | |
575 } | |
576 | |
577 uint flags() { return 1; } | |
578 } | |
579 | |
580 class TypeInfo_StaticArray : TypeInfo | |
581 { | |
582 char[] toString() | |
583 { | |
584 return value.toString() ~ "[" ~ std.string.toString(len) ~ "]"; | |
585 } | |
586 | |
587 int opEquals(Object o) | |
588 { TypeInfo_StaticArray c; | |
589 | |
590 return cast(int) | |
591 (this is o || | |
592 ((c = cast(TypeInfo_StaticArray)o) !is null && | |
593 this.len == c.len && | |
594 this.value == c.value)); | |
595 } | |
596 | |
597 hash_t getHash(void *p) | |
598 { size_t sz = value.tsize(); | |
599 hash_t hash = 0; | |
600 for (size_t i = 0; i < len; i++) | |
601 hash += value.getHash(p + i * sz); | |
602 return hash; | |
603 } | |
604 | |
605 int equals(void *p1, void *p2) | |
606 { | |
607 size_t sz = value.tsize(); | |
608 | |
609 for (size_t u = 0; u < len; u++) | |
610 { | |
611 if (!value.equals(p1 + u * sz, p2 + u * sz)) | |
612 return 0; | |
613 } | |
614 return 1; | |
615 } | |
616 | |
617 int compare(void *p1, void *p2) | |
618 { | |
619 size_t sz = value.tsize(); | |
620 | |
621 for (size_t u = 0; u < len; u++) | |
622 { | |
623 int result = value.compare(p1 + u * sz, p2 + u * sz); | |
624 if (result) | |
625 return result; | |
626 } | |
627 return 0; | |
628 } | |
629 | |
630 size_t tsize() | |
631 { | |
632 return len * value.tsize(); | |
633 } | |
634 | |
635 void swap(void *p1, void *p2) | |
636 { void* tmp; | |
637 size_t sz = value.tsize(); | |
638 ubyte[16] buffer; | |
639 void* pbuffer; | |
640 | |
641 if (sz < buffer.sizeof) | |
642 tmp = buffer.ptr; | |
643 else | |
644 tmp = pbuffer = (new void[sz]).ptr; | |
645 | |
646 for (size_t u = 0; u < len; u += sz) | |
647 { size_t o = u * sz; | |
648 memcpy(tmp, p1 + o, sz); | |
649 memcpy(p1 + o, p2 + o, sz); | |
650 memcpy(p2 + o, tmp, sz); | |
651 } | |
652 if (pbuffer) | |
653 delete pbuffer; | |
654 } | |
655 | |
656 void[] init() { return value.init(); } | |
657 TypeInfo next() { return value; } | |
658 uint flags() { return value.flags(); } | |
659 | |
660 TypeInfo value; | |
661 size_t len; | |
662 } | |
663 | |
664 class TypeInfo_AssociativeArray : TypeInfo | |
665 { | |
666 char[] toString() | |
667 { | |
668 return value.toString() ~ "[" ~ key.toString() ~ "]"; | |
669 } | |
670 | |
671 int opEquals(Object o) | |
672 { TypeInfo_AssociativeArray c; | |
673 | |
674 return this is o || | |
675 ((c = cast(TypeInfo_AssociativeArray)o) !is null && | |
676 this.key == c.key && | |
677 this.value == c.value); | |
678 } | |
679 | |
680 // BUG: need to add the rest of the functions | |
681 | |
682 size_t tsize() | |
683 { | |
684 return (char[int]).sizeof; | |
685 } | |
686 | |
687 TypeInfo next() { return value; } | |
688 uint flags() { return 1; } | |
689 | |
690 TypeInfo value; | |
691 TypeInfo key; | |
692 } | |
693 | |
694 class TypeInfo_Function : TypeInfo | |
695 { | |
696 char[] toString() | |
697 { | |
698 return next.toString() ~ "()"; | |
699 } | |
700 | |
701 int opEquals(Object o) | |
702 { TypeInfo_Function c; | |
703 | |
704 return this is o || | |
705 ((c = cast(TypeInfo_Function)o) !is null && | |
706 this.next == c.next); | |
707 } | |
708 | |
709 // BUG: need to add the rest of the functions | |
710 | |
711 size_t tsize() | |
712 { | |
713 return 0; // no size for functions | |
714 } | |
715 | |
716 TypeInfo next; | |
717 } | |
718 | |
719 class TypeInfo_Delegate : TypeInfo | |
720 { | |
721 char[] toString() | |
722 { | |
723 return next.toString() ~ " delegate()"; | |
724 } | |
725 | |
726 int opEquals(Object o) | |
727 { TypeInfo_Delegate c; | |
728 | |
729 return this is o || | |
730 ((c = cast(TypeInfo_Delegate)o) !is null && | |
731 this.next == c.next); | |
732 } | |
733 | |
734 // BUG: need to add the rest of the functions | |
735 | |
736 size_t tsize() | |
737 { alias int delegate() dg; | |
738 return dg.sizeof; | |
739 } | |
740 | |
741 uint flags() { return 1; } | |
742 | |
743 TypeInfo next; | |
744 } | |
745 | |
746 class TypeInfo_Class : TypeInfo | |
747 { | |
748 char[] toString() { return info.name; } | |
749 | |
750 int opEquals(Object o) | |
751 { TypeInfo_Class c; | |
752 | |
753 return this is o || | |
754 ((c = cast(TypeInfo_Class)o) !is null && | |
755 this.info.name == c.classinfo.name); | |
756 } | |
757 | |
758 hash_t getHash(void *p) | |
759 { | |
760 Object o = *cast(Object*)p; | |
761 assert(o); | |
762 return o.toHash(); | |
763 } | |
764 | |
765 int equals(void *p1, void *p2) | |
766 { | |
767 Object o1 = *cast(Object*)p1; | |
768 Object o2 = *cast(Object*)p2; | |
769 | |
770 return (o1 is o2) || (o1 && o1.opEquals(o2)); | |
771 } | |
772 | |
773 int compare(void *p1, void *p2) | |
774 { | |
775 Object o1 = *cast(Object*)p1; | |
776 Object o2 = *cast(Object*)p2; | |
777 int c = 0; | |
778 | |
779 // Regard null references as always being "less than" | |
780 if (o1 !is o2) | |
781 { | |
782 if (o1) | |
783 { if (!o2) | |
784 c = 1; | |
785 else | |
786 c = o1.opCmp(o2); | |
787 } | |
788 else | |
789 c = -1; | |
790 } | |
791 return c; | |
792 } | |
793 | |
794 size_t tsize() | |
795 { | |
796 return Object.sizeof; | |
797 } | |
798 | |
799 uint flags() { return 1; } | |
800 | |
801 OffsetTypeInfo[] offTi() | |
802 { | |
803 return (info.flags & 4) ? info.offTi : null; | |
804 } | |
805 | |
806 ClassInfo info; | |
807 } | |
808 | |
809 class TypeInfo_Interface : TypeInfo | |
810 { | |
811 char[] toString() { return info.name; } | |
812 | |
813 int opEquals(Object o) | |
814 { TypeInfo_Interface c; | |
815 | |
816 return this is o || | |
817 ((c = cast(TypeInfo_Interface)o) !is null && | |
818 this.info.name == c.classinfo.name); | |
819 } | |
820 | |
821 hash_t getHash(void *p) | |
822 { | |
823 Interface* pi = **cast(Interface ***)*cast(void**)p; | |
824 Object o = cast(Object)(*cast(void**)p - pi.offset); | |
825 assert(o); | |
826 return o.toHash(); | |
827 } | |
828 | |
829 int equals(void *p1, void *p2) | |
830 { | |
831 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
832 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
833 pi = **cast(Interface ***)*cast(void**)p2; | |
834 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
835 | |
836 return o1 == o2 || (o1 && o1.opCmp(o2) == 0); | |
837 } | |
838 | |
839 int compare(void *p1, void *p2) | |
840 { | |
841 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
842 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
843 pi = **cast(Interface ***)*cast(void**)p2; | |
844 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
845 int c = 0; | |
846 | |
847 // Regard null references as always being "less than" | |
848 if (o1 != o2) | |
849 { | |
850 if (o1) | |
851 { if (!o2) | |
852 c = 1; | |
853 else | |
854 c = o1.opCmp(o2); | |
855 } | |
856 else | |
857 c = -1; | |
858 } | |
859 return c; | |
860 } | |
861 | |
862 size_t tsize() | |
863 { | |
864 return Object.sizeof; | |
865 } | |
866 | |
867 uint flags() { return 1; } | |
868 | |
869 ClassInfo info; | |
870 } | |
871 | |
872 class TypeInfo_Struct : TypeInfo | |
873 { | |
874 char[] toString() { return name; } | |
875 | |
876 int opEquals(Object o) | |
877 { TypeInfo_Struct s; | |
878 | |
879 return this is o || | |
880 ((s = cast(TypeInfo_Struct)o) !is null && | |
881 this.name == s.name && | |
882 this.init.length == s.init.length); | |
883 } | |
884 | |
885 hash_t getHash(void *p) | |
886 { hash_t h; | |
887 | |
888 assert(p); | |
889 if (xtoHash) | |
890 { //printf("getHash() using xtoHash\n"); | |
891 h = (*xtoHash)(p); | |
892 } | |
893 else | |
894 { | |
895 //printf("getHash() using default hash\n"); | |
896 // A sorry hash algorithm. | |
897 // Should use the one for strings. | |
898 // BUG: relies on the GC not moving objects | |
899 for (size_t i = 0; i < init.length; i++) | |
900 { h = h * 9 + *cast(ubyte*)p; | |
901 p++; | |
902 } | |
903 } | |
904 return h; | |
905 } | |
906 | |
907 int equals(void *p2, void *p1) | |
908 { int c; | |
909 | |
910 if (p1 == p2) | |
911 c = 1; | |
912 else if (!p1 || !p2) | |
913 c = 0; | |
914 else if (xopEquals) | |
915 c = (*xopEquals)(p1, p2); | |
916 else | |
917 // BUG: relies on the GC not moving objects | |
918 c = (memcmp(p1, p2, init.length) == 0); | |
919 return c; | |
920 } | |
921 | |
922 int compare(void *p2, void *p1) | |
923 { | |
924 int c = 0; | |
925 | |
926 // Regard null references as always being "less than" | |
927 if (p1 != p2) | |
928 { | |
929 if (p1) | |
930 { if (!p2) | |
931 c = 1; | |
932 else if (xopCmp) | |
933 c = (*xopCmp)(p1, p2); | |
934 else | |
935 // BUG: relies on the GC not moving objects | |
936 c = memcmp(p1, p2, init.length); | |
937 } | |
938 else | |
939 c = -1; | |
940 } | |
941 return c; | |
942 } | |
943 | |
944 size_t tsize() | |
945 { | |
946 return init.length; | |
947 } | |
948 | |
949 void[] init() { return m_init; } | |
950 | |
951 uint flags() { return m_flags; } | |
952 | |
953 char[] name; | |
954 void[] m_init; // initializer; init.ptr == null if 0 initialize | |
955 | |
956 hash_t function(void*) xtoHash; | |
957 int function(void*,void*) xopEquals; | |
958 int function(void*,void*) xopCmp; | |
959 char[] function(void*) xtoString; | |
960 | |
961 uint m_flags; | |
962 } | |
963 | |
964 class TypeInfo_Tuple : TypeInfo | |
965 { | |
966 TypeInfo[] elements; | |
967 | |
968 char[] toString() | |
969 { | |
970 char[] s; | |
971 s = "("; | |
972 foreach (i, element; elements) | |
973 { | |
974 if (i) | |
975 s ~= ','; | |
976 s ~= element.toString(); | |
977 } | |
978 s ~= ")"; | |
979 return s; | |
980 } | |
981 | |
982 int opEquals(Object o) | |
983 { | |
984 if (this is o) | |
985 return 1; | |
986 | |
987 auto t = cast(TypeInfo_Tuple)o; | |
988 if (t && elements.length == t.elements.length) | |
989 { | |
990 for (size_t i = 0; i < elements.length; i++) | |
991 { | |
992 if (elements[i] != t.elements[i]) | |
993 return 0; | |
994 } | |
995 return 1; | |
996 } | |
997 return 0; | |
998 } | |
999 | |
1000 hash_t getHash(void *p) | |
1001 { | |
1002 assert(0); | |
1003 } | |
1004 | |
1005 int equals(void *p1, void *p2) | |
1006 { | |
1007 assert(0); | |
1008 } | |
1009 | |
1010 int compare(void *p1, void *p2) | |
1011 { | |
1012 assert(0); | |
1013 } | |
1014 | |
1015 size_t tsize() | |
1016 { | |
1017 assert(0); | |
1018 } | |
1019 | |
1020 void swap(void *p1, void *p2) | |
1021 { | |
1022 assert(0); | |
1023 } | |
1024 } | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
1025 +/ |
1 | 1026 |
1027 /** | |
1028 * All recoverable exceptions should be derived from class Exception. | |
1029 */ | |
1030 class Exception : Object | |
1031 { | |
1032 char[] msg; | |
1033 | |
1034 /** | |
1035 * Constructor; msg is a descriptive message for the exception. | |
1036 */ | |
1037 this(char[] msg) | |
1038 { | |
1039 this.msg = msg; | |
1040 } | |
1041 | |
1042 void print() | |
1043 { | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
1044 auto str = toString(); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
1045 printf("%.*s\n", str.length, str.ptr); |
1 | 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; |