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;
|
|
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 +/
|