comparison lphobos/internal/aaA.d @ 109:5ab8e92611f9 trunk

[svn r113] Added initial support for associative arrays (AAs). Fixed some problems with the string runtime support functions. Fixed initialization of array of structs. Fixed slice assignment where LHS is slice but RHS is dynamic array. Fixed problems with result of assignment expressions. Fixed foreach problems with key type mismatches.
author lindquist
date Wed, 21 Nov 2007 04:13:15 +0100
parents 288fe1029e1f
children facc562f5674
comparison
equal deleted inserted replaced
108:288fe1029e1f 109:5ab8e92611f9
25 * be misrepresented as being the original software. 25 * be misrepresented as being the original software.
26 * o This notice may not be removed or altered from any source 26 * o This notice may not be removed or altered from any source
27 * distribution. 27 * distribution.
28 */ 28 */
29 29
30 /*
31 * Modified for LLVMDC by Tomas Lindquist Olsen.
32 * The DMD implementation wont quite work due to the differences in how
33 * structs are handled.
34 */
35
30 36
31 //import std.stdio; 37 //import std.stdio;
32 import std.c.stdarg; 38 import std.c.stdarg;
33 import std.c.stdio; 39 import std.c.stdio;
34 import std.c.stdlib; 40 import std.c.stdlib;
35 import std.c.string; 41 import std.c.string;
36 import std.string; 42 //import std.string;
37 43
38 import std.outofmemory; 44 import std.outofmemory;
39 45
40 // Auto-rehash and pre-allocate - Dave Fladebo 46 // Auto-rehash and pre-allocate - Dave Fladebo
41 47
49 1610612741UL, 4294967291UL 55 1610612741UL, 4294967291UL
50 ]; 56 ];
51 57
52 /* This is the type of the return value for dynamic arrays. 58 /* This is the type of the return value for dynamic arrays.
53 * It should be a type that is returned in registers. 59 * It should be a type that is returned in registers.
54 * Although DMD will return types of Array in registers, 60 */
55 * gcc will not, so we instead use a 'long'. 61 alias Array ArrayRet_t;
56 */ 62
57 alias long ArrayRet_t; 63 pragma(LLVM_internal, "notypeinfo")
58
59 struct Array 64 struct Array
60 { 65 {
61 size_t length; 66 size_t length;
62 void* ptr; 67 void* ptr;
63 } 68 }
64 69
70 pragma(LLVM_internal, "notypeinfo")
65 struct aaA 71 struct aaA
66 { 72 {
67 aaA *left; 73 aaA *left;
68 aaA *right; 74 aaA *right;
69 hash_t hash; 75 hash_t hash;
70 /* key */ 76 /* key */
71 /* value */ 77 /* value */
72 } 78 }
73 79
80 pragma(LLVM_internal, "notypeinfo")
74 struct BB 81 struct BB
75 { 82 {
76 aaA*[] b; 83 aaA*[] b;
77 size_t nodes; // total number of aaA nodes 84 size_t nodes; // total number of aaA nodes
78 } 85 }
79 86
80 /* This is the type actually seen by the programmer, although 87 /* This is the type actually seen by the programmer, although
81 * it is completely opaque. 88 * it is completely opaque.
82 */ 89 */
83 90
84 struct AA 91 alias BB* AA;
85 {
86 BB* a;
87 }
88 92
89 /********************************** 93 /**********************************
90 * Align to next pointer boundary, so that 94 * Align to next pointer boundary, so that
91 * GC won't be faced with misaligned pointers 95 * GC won't be faced with misaligned pointers
92 * in value. 96 * in value.
196 break; 200 break;
197 len++; 201 len++;
198 } 202 }
199 } 203 }
200 204
201 if (aa.a) 205 if (aa)
202 { 206 {
203 foreach (e; aa.a.b) 207 foreach (e; aa.b)
204 { 208 {
205 if (e) 209 if (e)
206 _aaLen_x(e); 210 _aaLen_x(e);
207 } 211 }
208 } 212 }
210 214
211 //printf("_aaLen()-\n"); 215 //printf("_aaLen()-\n");
212 } 216 }
213 body 217 body
214 { 218 {
215 return aa.a ? aa.a.nodes : 0; 219 return aa ? aa.nodes : 0;
216 } 220 }
217 221
218 222
219 /************************************************* 223 /*************************************************
220 * Get pointer to value in associative array indexed by key. 224 * Get pointer to value in associative array indexed by key.
221 * Add entry for key if it is not already there. 225 * Add entry for key if it is not already there.
222 */ 226 */
223 227
224 void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...) 228 void* _aaGet(AA* aa, TypeInfo keyti, void* pkey, size_t valuesize)
225 in 229 in
226 { 230 {
227 assert(aa); 231 assert(aa);
228 } 232 }
229 out (result) 233 out (result)
230 { 234 {
231 assert(result); 235 assert(result);
232 assert(aa.a); 236 assert(*aa);
233 assert(aa.a.b.length); 237 assert((*aa).b.length);
234 //assert(_aaInAh(*aa.a, key)); 238 //assert(_aaInAh(*aa, key));
235 } 239 }
236 body 240 body
237 { 241 {
238 auto pkey = cast(void *)(&valuesize + 1); 242 //auto pkey = cast(void *)(&valuesize + 1);
239 size_t i; 243 size_t i;
240 aaA* e; 244 aaA* e;
241 auto keysize = aligntsize(keyti.tsize()); 245 auto keysize = aligntsize(keyti.tsize());
242 246
243 if (!aa.a) 247 if (!*aa)
244 aa.a = new BB(); 248 *aa = new BB();
245 249
246 if (!aa.a.b.length) 250 if (!(*aa).b.length)
247 { 251 {
248 alias aaA *pa; 252 alias aaA *pa;
249 auto len = prime_list[0]; 253 auto len = prime_list[0];
250 254
251 aa.a.b = new pa[len]; 255 (*aa).b = new pa[len];
252 } 256 }
253 257
254 auto key_hash = keyti.getHash(pkey); 258 auto key_hash = keyti.getHash(pkey);
255 //printf("hash = %d\n", key_hash); 259 //printf("hash = %d\n", key_hash);
256 i = key_hash % aa.a.b.length; 260 i = key_hash % (*aa).b.length;
257 auto pe = &aa.a.b[i]; 261 auto pe = &(*aa).b[i];
258 while ((e = *pe) != null) 262 while ((e = *pe) != null)
259 { 263 {
260 if (key_hash == e.hash) 264 if (key_hash == e.hash)
261 { 265 {
262 auto c = keyti.compare(pkey, e + 1); 266 auto c = keyti.compare(pkey, e + 1);
273 e = cast(aaA *) cast(void*) new void[aaA.sizeof + keysize + valuesize]; 277 e = cast(aaA *) cast(void*) new void[aaA.sizeof + keysize + valuesize];
274 memcpy(e + 1, pkey, keysize); 278 memcpy(e + 1, pkey, keysize);
275 e.hash = key_hash; 279 e.hash = key_hash;
276 *pe = e; 280 *pe = e;
277 281
278 auto nodes = ++aa.a.nodes; 282 auto nodes = ++(*aa).nodes;
279 //printf("length = %d, nodes = %d\n", (*aa.a).length, nodes); 283 //printf("length = %d, nodes = %d\n", (*aa).length, nodes);
280 if (nodes > aa.a.b.length * 4) 284 if (nodes > (*aa).b.length * 4)
281 { 285 {
282 _aaRehash(aa,keyti); 286 _aaRehash(aa,keyti);
283 } 287 }
284 288
285 Lret: 289 Lret:
290 /************************************************* 294 /*************************************************
291 * Get pointer to value in associative array indexed by key. 295 * Get pointer to value in associative array indexed by key.
292 * Returns null if it is not already there. 296 * Returns null if it is not already there.
293 */ 297 */
294 298
295 void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...) 299 void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, void* pkey)
296 { 300 {
297 //printf("_aaGetRvalue(valuesize = %u)\n", valuesize); 301 //printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
298 if (!aa.a) 302 if (!aa)
299 return null; 303 return null;
300 304
301 auto pkey = cast(void *)(&valuesize + 1); 305 //auto pkey = cast(void *)(&valuesize + 1);
302 auto keysize = aligntsize(keyti.tsize()); 306 auto keysize = aligntsize(keyti.tsize());
303 auto len = aa.a.b.length; 307 auto len = aa.b.length;
304 308
305 if (len) 309 if (len)
306 { 310 {
307 auto key_hash = keyti.getHash(pkey); 311 auto key_hash = keyti.getHash(pkey);
308 //printf("hash = %d\n", key_hash); 312 //printf("hash = %d\n", key_hash);
309 size_t i = key_hash % len; 313 size_t i = key_hash % len;
310 auto e = aa.a.b[i]; 314 auto e = aa.b[i];
311 while (e != null) 315 while (e != null)
312 { 316 {
313 if (key_hash == e.hash) 317 if (key_hash == e.hash)
314 { 318 {
315 auto c = keyti.compare(pkey, e + 1); 319 auto c = keyti.compare(pkey, e + 1);
330 * Returns: 334 * Returns:
331 * null not in aa 335 * null not in aa
332 * !=null in aa, return pointer to value 336 * !=null in aa, return pointer to value
333 */ 337 */
334 338
335 void* _aaIn(AA aa, TypeInfo keyti, ...) 339 void* _aaIn(AA aa, TypeInfo keyti, void* pkey)
336 in 340 in
337 { 341 {
338 } 342 }
339 out (result) 343 out (result)
340 { 344 {
341 //assert(result == 0 || result == 1); 345 //assert(result == 0 || result == 1);
342 } 346 }
343 body 347 body
344 { 348 {
345 if (aa.a) 349 if (aa)
346 { 350 {
347 auto pkey = cast(void *)(&keyti + 1); 351 //auto pkey = cast(void *)(&keyti + 1);
348 352
349 //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr); 353 //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.length, cast(uint)aa.ptr);
350 auto len = aa.a.b.length; 354 auto len = aa.b.length;
351 355
352 if (len) 356 if (len)
353 { 357 {
354 auto key_hash = keyti.getHash(pkey); 358 auto key_hash = keyti.getHash(pkey);
355 //printf("hash = %d\n", key_hash); 359 //printf("hash = %d\n", key_hash);
356 size_t i = key_hash % len; 360 size_t i = key_hash % len;
357 auto e = aa.a.b[i]; 361 auto e = aa.b[i];
358 while (e != null) 362 while (e != null)
359 { 363 {
360 if (key_hash == e.hash) 364 if (key_hash == e.hash)
361 { 365 {
362 auto c = keyti.compare(pkey, e + 1); 366 auto c = keyti.compare(pkey, e + 1);
378 /************************************************* 382 /*************************************************
379 * Delete key entry in aa[]. 383 * Delete key entry in aa[].
380 * If key is not in aa[], do nothing. 384 * If key is not in aa[], do nothing.
381 */ 385 */
382 386
383 void _aaDel(AA aa, TypeInfo keyti, ...) 387 void _aaDel(AA aa, TypeInfo keyti, void* pkey)
384 { 388 {
385 auto pkey = cast(void *)(&keyti + 1); 389 //auto pkey = cast(void *)(&keyti + 1);
386 aaA* e; 390 aaA* e;
387 391
388 if (aa.a && aa.a.b.length) 392 if (aa && aa.b.length)
389 { 393 {
390 auto key_hash = keyti.getHash(pkey); 394 auto key_hash = keyti.getHash(pkey);
391 //printf("hash = %d\n", key_hash); 395 //printf("hash = %d\n", key_hash);
392 size_t i = key_hash % aa.a.b.length; 396 size_t i = key_hash % aa.b.length;
393 auto pe = &aa.a.b[i]; 397 auto pe = &aa.b[i];
394 while ((e = *pe) != null) // null means not found 398 while ((e = *pe) != null) // null means not found
395 { 399 {
396 if (key_hash == e.hash) 400 if (key_hash == e.hash)
397 { 401 {
398 auto c = keyti.compare(pkey, e + 1); 402 auto c = keyti.compare(pkey, e + 1);
421 while (*pe); 425 while (*pe);
422 *pe = e.right; 426 *pe = e.right;
423 e.right = null; 427 e.right = null;
424 } 428 }
425 429
426 aa.a.nodes--; 430 aa.nodes--;
427 431
428 // Should notify GC that e can be free'd now 432 // Should notify GC that e can be free'd now
429 break; 433 break;
430 } 434 }
431 pe = (c < 0) ? &e.left : &e.right; 435 pe = (c < 0) ? &e.left : &e.right;
468 } 472 }
469 e = e.right; 473 e = e.right;
470 } while (e != null); 474 } while (e != null);
471 } 475 }
472 476
473 if (aa.a) 477 if (aa)
474 { 478 {
475 a.length = _aaLen(aa); 479 a.length = _aaLen(aa);
476 a.ptr = (new void[a.length * valuesize]).ptr; 480 a.ptr = (new void[a.length * valuesize]).ptr;
477 resi = 0; 481 resi = 0;
478 foreach (e; aa.a.b) 482 foreach (e; aa.b)
479 { 483 {
480 if (e) 484 if (e)
481 _aaValues_x(e); 485 _aaValues_x(e);
482 } 486 }
483 assert(resi == a.length); 487 assert(resi == a.length);
484 } 488 }
485 return *cast(ArrayRet_t*)(&a); 489 return a;
486 } 490 }
487 491
488 492
489 /******************************************** 493 /********************************************
490 * Rehash an array. 494 * Rehash an array.
491 */ 495 */
492 496
493 void* _aaRehash(AA* paa, TypeInfo keyti) 497 void* _aaRehash(AA* paa, TypeInfo keyti)
494 in 498 in
495 { 499 {
500 assert(paa);
496 //_aaInvAh(paa); 501 //_aaInvAh(paa);
497 } 502 }
498 out (result) 503 out (result)
499 { 504 {
500 //_aaInvAh(result); 505 //_aaInvAh(result);
547 olde = left; 552 olde = left;
548 } 553 }
549 } 554 }
550 555
551 //printf("Rehash\n"); 556 //printf("Rehash\n");
552 if (paa.a) 557 if (paa)
553 { 558 {
554 auto aa = paa.a; 559 auto aa = *paa;
555 auto len = _aaLen(*paa); 560 auto len = _aaLen(*paa);
556 if (len) 561 if (len)
557 { size_t i; 562 { size_t i;
558 563
559 for (i = 0; i < prime_list.length - 1; i++) 564 for (i = 0; i < prime_list.length - 1; i++)
571 } 576 }
572 577
573 newb.nodes = aa.nodes; 578 newb.nodes = aa.nodes;
574 } 579 }
575 580
576 *paa.a = newb; 581 **paa = newb;
577 } 582 }
578 return (*paa).a; 583 return *paa;
579 } 584 }
580 585
581 586
582 /******************************************** 587 /********************************************
583 * Produce array of N byte keys from aa. 588 * Produce array of N byte keys from aa.
605 } while (e != null); 610 } while (e != null);
606 } 611 }
607 612
608 auto len = _aaLen(aa); 613 auto len = _aaLen(aa);
609 if (!len) 614 if (!len)
610 return 0; 615 return ArrayRet_t.init;
611 res = cast(byte[])new void[len * keysize]; 616 res = cast(byte[])new void[len * keysize];
612 resi = 0; 617 resi = 0;
613 foreach (e; aa.a.b) 618 foreach (e; aa.b)
614 { 619 {
615 if (e) 620 if (e)
616 _aaKeys_x(e); 621 _aaKeys_x(e);
617 } 622 }
618 assert(resi == len); 623 assert(resi == len);
619 624
620 Array a; 625 return Array(len, res.ptr);
621 a.length = len;
622 a.ptr = res.ptr;
623 return *cast(ArrayRet_t*)(&a);
624 } 626 }
625 627
626 628
627 /********************************************** 629 /**********************************************
628 * 'apply' for associative arrays - to support foreach 630 * 'apply' for associative arrays - to support foreach
637 assert(aligntsize(keysize) == keysize); 639 assert(aligntsize(keysize) == keysize);
638 } 640 }
639 body 641 body
640 { int result; 642 { int result;
641 643
642 //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg); 644 //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
643 645
644 int treewalker(aaA* e) 646 int treewalker(aaA* e)
645 { int result; 647 { int result;
646 648
647 do 649 do
664 } while (e); 666 } while (e);
665 667
666 return result; 668 return result;
667 } 669 }
668 670
669 if (aa.a) 671 if (aa)
670 { 672 {
671 foreach (e; aa.a.b) 673 foreach (e; aa.b)
672 { 674 {
673 if (e) 675 if (e)
674 { 676 {
675 result = treewalker(e); 677 result = treewalker(e);
676 if (result) 678 if (result)
690 assert(aligntsize(keysize) == keysize); 692 assert(aligntsize(keysize) == keysize);
691 } 693 }
692 body 694 body
693 { int result; 695 { int result;
694 696
695 //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg); 697 //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
696 698
697 int treewalker(aaA* e) 699 int treewalker(aaA* e)
698 { int result; 700 { int result;
699 701
700 do 702 do
717 } while (e); 719 } while (e);
718 720
719 return result; 721 return result;
720 } 722 }
721 723
722 if (aa.a) 724 if (aa)
723 { 725 {
724 foreach (e; aa.a.b) 726 foreach (e; aa.b)
725 { 727 {
726 if (e) 728 if (e)
727 { 729 {
728 result = treewalker(e); 730 result = treewalker(e);
729 if (result) 731 if (result)