comparison dmdscript_tango/property.d @ 0:55c2951c07be

initial, files origin, premoved tree
author saaadel
date Sun, 24 Jan 2010 12:34:47 +0200
parents
children 8363a4bf6a8f
comparison
equal deleted inserted replaced
-1:000000000000 0:55c2951c07be
1
2 /* Digital Mars DMDScript source code.
3 * Copyright (c) 2000-2002 by Chromium Communications
4 * D version Copyright (c) 2004-2006 by Digital Mars
5 * All Rights Reserved
6 * written by Walter Bright
7 * www.digitalmars.com
8 * Use at your own risk. There is no warranty, express or implied.
9 * License for redistribution is by the GNU General Public License in gpl.txt.
10 *
11 * A binary, non-exclusive license for commercial use can be
12 * purchased from www.digitalmars.com/dscript/buy.html.
13 *
14 * DMDScript is implemented in the D Programming Language,
15 * www.digitalmars.com/d/
16 *
17 * For a C++ implementation of DMDScript, including COM support,
18 * see www.digitalmars.com/dscript/cppscript.html.
19 */
20
21
22 module dmdscript.property;
23
24 import dmdscript.script;
25 import dmdscript.value;
26 import dmdscript.identifier;
27
28 import std.c.string;
29
30 // attribute flags
31 enum
32 {
33 ReadOnly = 0x001,
34 DontEnum = 0x002,
35 DontDelete = 0x004,
36 Internal = 0x008,
37 Deleted = 0x010,
38 Locked = 0x020,
39 DontOverride = 0x040,
40 KeyWord = 0x080,
41 DebugFree = 0x100, // for debugging help
42 Instantiate = 0x200, // For COM named item namespace support
43 }
44
45 struct Property
46 {
47 uint attributes;
48
49 Value value;
50 }
51
52 extern (C)
53 {
54 /* These functions are part of the internal implementation of Phobos
55 * associative arrays. It's faster to use them when we have precomputed
56 * values to use.
57 */
58
59 struct Array
60 {
61 int length;
62 void* ptr;
63 }
64
65 struct aaA
66 {
67 aaA *left;
68 aaA *right;
69 hash_t hash;
70 /* key */
71 /* value */
72 }
73
74 struct BB
75 {
76 aaA*[] b;
77 size_t nodes; // total number of aaA nodes
78 }
79
80 struct AA
81 {
82 BB* a;
83 version (X86_64)
84 {
85 }
86 else
87 {
88 // This is here only to retain binary compatibility with the
89 // old way we did AA's. Should eventually be removed.
90 int reserved;
91 }
92 }
93
94 long _aaRehash(AA* paa, TypeInfo keyti);
95
96 /************************
97 * Alternate Get() version
98 */
99
100 Property* _aaGetY(hash_t hash, Property[Value]* bb, Value* key)
101 {
102 aaA* e;
103 auto aa = cast(AA*)bb;
104
105 if (!aa.a)
106 aa.a = new BB();
107
108 auto aalen = aa.a.b.length;
109 if (!aalen)
110 {
111 alias aaA *pa;
112
113 aalen = 97;
114 aa.a.b = new pa[aalen];
115 }
116
117 //printf("hash = %d\n", hash);
118 size_t i = hash % aalen;
119 auto pe = &aa.a.b[i];
120 while ((e = *pe) != null)
121 {
122 if (hash == e.hash)
123 {
124 Value* v = cast(Value*)(e + 1);
125 if (key.vtype == V_NUMBER)
126 { if (v.vtype == V_NUMBER && key.number == v.number)
127 goto Lret;
128 }
129 else if (key.vtype == V_STRING)
130 { if (v.vtype == V_STRING && key.string is v.string)
131 goto Lret;
132 }
133 auto c = key.opCmp(v);
134 if (c == 0)
135 goto Lret;
136 pe = (c < 0) ? &e.left : &e.right;
137 }
138 else
139 pe = (hash < e.hash) ? &e.left : &e.right;
140 }
141
142 // Not found, create new elem
143 //printf("\tcreate new one\n");
144 e = cast(aaA *) cast(void*) new void[aaA.sizeof + Value.sizeof + Property.sizeof];
145 std.c.string.memcpy(e + 1, key, Value.sizeof);
146 e.hash = hash;
147 *pe = e;
148
149 auto nodes = ++aa.a.nodes;
150 //printf("length = %d, nodes = %d\n", (*aa).length, nodes);
151 if (nodes > aalen * 4)
152 {
153 _aaRehash(aa, typeid(Value));
154 }
155
156 Lret:
157 return cast(Property*)(cast(void *)(e + 1) + Value.sizeof);
158 }
159
160 /************************************
161 * Alternate In() with precomputed values.
162 */
163
164 Property* _aaInY(hash_t hash, Property[Value] bb, Value* key)
165 {
166 size_t i;
167 AA aa = *cast(AA*)&bb;
168
169 //printf("_aaIn(), aa.length = %d, .ptr = %x\n", aa.length, cast(uint)aa.ptr);
170 if (aa.a && aa.a.b.length)
171 {
172 //printf("hash = %d\n", hash);
173 i = hash % aa.a.b.length;
174 auto e = aa.a.b[i];
175 while (e != null)
176 {
177 if (hash == e.hash)
178 {
179 Value* v = cast(Value*)(e + 1);
180 if (key.vtype == V_NUMBER && v.vtype == V_NUMBER &&
181 key.number == v.number)
182 goto Lfound;
183 auto c = key.opCmp(v);
184 if (c == 0)
185 {
186 Lfound:
187 return cast(Property*)(cast(void *)(e + 1) + Value.sizeof);
188 }
189 else
190 e = (c < 0) ? e.left : e.right;
191 }
192 else
193 e = (hash < e.hash) ? e.left : e.right;
194 }
195 }
196
197 // Not found
198 return null;
199 }
200 }
201
202 /*********************************** PropTable *********************/
203
204 struct PropTable
205 {
206 Property[Value] table;
207 PropTable* previous;
208
209 int opApply(int delegate(inout Property) dg)
210 { int result;
211
212 foreach (inout Property p; table)
213 {
214 result = dg(p);
215 if (result)
216 break;
217 }
218 return result;
219 }
220
221 int opApply(int delegate(inout Value, inout Property) dg)
222 { int result;
223
224 foreach (Value key, inout Property p; table)
225 {
226 result = dg(key, p);
227 if (result)
228 break;
229 }
230 return result;
231 }
232
233 /*******************************
234 * Look up name and get its corresponding Property.
235 * Return null if not found.
236 */
237
238 Property *getProperty(d_string name)
239 {
240 Value* v;
241 Property *p;
242
243 v = get(name, Value.calcHash(name));
244 if (!v)
245 return null;
246
247 // Work backwards from &p->value to p
248 p = cast(Property *)(cast(char *)v - uint.sizeof /*Property.value.offsetof*/);
249
250 return p;
251 }
252
253 Value* get(Value* key, hash_t hash)
254 {
255 uint i;
256 Property *p;
257 PropTable *t;
258
259 //writefln("get(key = '%s', hash = x%x)", key.toString(), hash);
260 assert(key.toHash() == hash);
261 t = this;
262 do
263 {
264 //writefln("\tt = %x", cast(uint)t);
265 // p = *key in t.table;
266 p = _aaInY(hash, t.table, key);
267
268 if (p)
269 { //writefln("\tfound");
270 //p.value.dump();
271 assert(&t.table[*key] == p);
272 //p.value.dump();
273 return &p.value;
274 }
275 t = t.previous;
276 } while (t);
277 //writefln("\tnot found");
278 return null; // not found
279 }
280
281 Value* get(d_uint32 index)
282 {
283 //writefln("get(index = %d)", index);
284 Value key;
285
286 key.putVnumber(index);
287 return get(&key, Value.calcHash(index));
288 }
289
290 Value* get(Identifier* id)
291 {
292 //writefln("get('%s', hash = x%x)", name, hash);
293 return get(&id.value, id.value.hash);
294 //return get(id.value.string, id.value.hash);
295 }
296
297 Value* get(d_string name, hash_t hash)
298 {
299 //writefln("get('%s', hash = x%x)", name, hash);
300 Value key;
301
302 key.putVstring(name);
303 return get(&key, hash);
304 }
305
306 /*******************************
307 * Determine if property exists for this object.
308 * The enumerable flag means the DontEnum attribute cannot be set.
309 */
310
311 int hasownproperty(Value* key, int enumerable)
312 {
313 Property* p;
314
315 p = *key in table;
316 return p && (!enumerable || !(p.attributes & DontEnum));
317 }
318
319 int hasproperty(Value* key)
320 {
321 return (*key in table) != null;
322 }
323
324 int hasproperty(d_string name)
325 {
326 Value v;
327
328 v.putVstring(name);
329 return hasproperty(&v);
330 }
331
332 Value* put(Value* key, hash_t hash, Value* value, uint attributes)
333 {
334 Property* p;
335
336 //writefln("put(key = %s, hash = x%x, value = %s, attributes = x%x)", key.toString(), hash, value.toString(), attributes);
337 //writefln("put(key = %s)", key.toString());
338 // p = &table[*key];
339 p = _aaGetY(hash, &table, key);
340 /+
341 {
342 size_t i;
343 aaA *e;
344 aaA **pe;
345 aaA*[]* aa = cast(aaA*[]*)&table;
346 size_t aalen;
347
348 aalen = (*aa).length;
349 if (!aalen)
350 {
351 alias aaA *pa;
352
353 aalen = 97 + 1;
354 *aa = new pa[aalen];
355 (*aa)[0] = cast(aaA *) cast(void*) new void[aaA.sizeof];
356 }
357
358 //printf("hash = %d\n", hash);
359 i = (hash % (aalen - 1)) + 1;
360 pe = &(*aa)[i];
361 while ((e = *pe) != null)
362 {
363 if (hash == e.hash)
364 {
365 Value* v = cast(Value*)(e + 1);
366 if (key.vtype == V_NUMBER)
367 { if (v.vtype == V_NUMBER && key.number == v.number)
368 goto Lfound;
369 }
370 else if (key.vtype == V_STRING)
371 { if (v.vtype == V_STRING && key.string is v.string)
372 goto Lfound;
373 }
374 auto c = key.opCmp(v);
375 if (c == 0)
376 {
377 Lfound:
378 p = cast(Property*)(v + 1);
379 goto Lx;
380 }
381 pe = (c < 0) ? &e.left : &e.right;
382 }
383 else
384 pe = (hash < e.hash) ? &e.left : &e.right;
385 }
386
387 // Not found, create new elem
388 //printf("\tcreate new one\n");
389 e = cast(aaA *) cast(void*) new void[aaA.sizeof + Value.sizeof + Property.sizeof];
390 memcpy(e + 1, key, Value.sizeof);
391 e.hash = hash;
392 *pe = e;
393
394 uint nodes = ++(*aa)[0].nodes;
395 //printf("length = %d, nodes = %d\n", (*aa).length, nodes);
396 if (nodes > aalen * 4)
397 {
398 _aaRehash(aa, typeid(Value));
399 }
400
401 p = cast(Property*)(cast(void *)(e + 1) + Value.sizeof);
402 }
403 +/
404 if (p.value.vtype != V_NONE)
405 {
406 Lx:
407 if (attributes & DontOverride ||
408 p.attributes & ReadOnly)
409 {
410 if (p.attributes & KeyWord)
411 return null;
412 return &vundefined;
413 }
414
415 PropTable* t = previous;
416 if (t)
417 {
418 do
419 { Property* q;
420 // q = *key in t.table;
421 q = _aaInY(hash, t.table, key);
422 if (q)
423 {
424 if (q.attributes & ReadOnly)
425 { p.attributes |= ReadOnly;
426 return &vundefined;
427 }
428 break;
429 }
430 t = t.previous;
431 } while (t);
432 }
433
434 // Overwrite property with new value
435 Value.copy(&p.value, value);
436 p.attributes = (attributes & ~DontOverride) | (p.attributes & (DontDelete | DontEnum));
437 return null;
438 }
439
440 // Not in table; create new entry
441
442 p.attributes = attributes & ~DontOverride;
443 Value.copy(&p.value, value);
444 assert(p.value == value);
445
446 return null; // success
447 }
448
449 Value* put(d_string name, Value* value, uint attributes)
450 {
451 Value key;
452
453 key.putVstring(name);
454
455 //writef("PropTable::put(%p, '%ls', hash = x%x)\n", this, d_string_ptr(name), key.toHash());
456 return put(&key, Value.calcHash(name), value, attributes);
457 }
458
459 Value* put(d_uint32 index, Value* value, uint attributes)
460 {
461 Value key;
462
463 key.putVnumber(index);
464
465 //writef("PropTable::put(%d)\n", index);
466 return put(&key, Value.calcHash(index), value, attributes);
467 }
468
469 Value* put(d_uint32 index, d_string string, uint attributes)
470 {
471 Value key;
472 Value value;
473
474 key.putVnumber(index);
475 value.putVstring(string);
476
477 return put(&key, Value.calcHash(index), &value, attributes);
478 }
479
480 int canput(Value* key, hash_t hash)
481 {
482 Property *p;
483 PropTable *t;
484
485 t = this;
486 do
487 {
488 // p = *key in t.table;
489 p = _aaInY(hash, t.table, key);
490 if (p)
491 { return (p.attributes & ReadOnly)
492 ? false : true;
493 }
494 t = t.previous;
495 } while (t);
496 return true; // success
497 }
498
499 int canput(d_string name)
500 {
501 Value v;
502
503 v.putVstring(name);
504
505 return canput(&v, v.toHash());
506 }
507
508 int del(Value* key)
509 {
510 Property *p;
511
512 //writef("PropTable::del('%ls')\n", d_string_ptr(key.toString()));
513 p = *key in table;
514 if (p)
515 {
516 if (p.attributes & DontDelete)
517 return false;
518 table.remove(*key);
519 }
520 return true; // not found
521 }
522
523 int del(d_string name)
524 {
525 Value v;
526
527 v.putVstring(name);
528
529 //writef("PropTable::del('%ls')\n", d_string_ptr(name));
530 return del(&v);
531 }
532
533 int del(d_uint32 index)
534 {
535 Value v;
536
537 v.putVnumber(index);
538
539 //writef("PropTable::del(%d)\n", index);
540 return del(&v);
541 }
542 }
543
544