/* CoreBasics.c */ #include "malloc.h" #include "CoreBasics.h" /* Basic Operations */ Nat Min(a, b) Nat a; Nat b; { if (a>b) return(b); else return(a); }; Nat Max(a, b) Nat a; Nat b; { if (a>b) return(a); else return(b); }; /* Bit Operations */ Nat powersOfTwo[32]= {0x1L, 0x2L, 0x4L, 0x8L, 0x10L, 0x20L, 0x40L, 0x80L, 0x100L, 0x200L, 0x400L, 0x800L, 0x1000L, 0x2000L, 0x4000L, 0x8000L, 0x10000L, 0x20000L, 0x40000L, 0x80000L, 0x100000L, 0x200000L, 0x400000L, 0x800000L, 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L, 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L}; Nat NBits(n) Nat n; { Nat i; if (n==0) return(0); for (i=1; i<32; i++) if (powersOfTwo[i]>=n) return(i); if (n<=NatLast) return(32); Die; }; Bool EBFN(container, index, containerSize) Nat container; Nat index; Nat containerSize; { return((container>>(containerSize-index-1))&1); }; /* Memory Management */ Ref MemoryAllocate(bytes) Nat bytes; { return((Ref)malloc(bytes)); }; /* String */ Bool StringEqual(first, second) String first; String second; { if (first==nil && second==nil) return(true); if (first==nil || second==nil) return (false); while (true) { if (*first==0 && *second==0) return (true); if (*first!=*second || *first==0 || *second==0) return (false); first+=1; second+=1; }; }; Nat StringLength(string) String string; { Nat length=0; if (string==nil) return(0); while (*string!=0) { string+=1; length+=1; }; return(length); }; String StringNew(size) Nat size; { return(MemoryAllocate(size+1)); }; void StringMove(fetch, store) char *fetch; char *store; { if (fetch==nil) return; while (*fetch!=0) { *store = *fetch; fetch+=1; store+=1; }; }; String StringCat(first, second) String first; String second; { Nat firstLength=StringLength(first); Nat secondLength=StringLength(second); String new=StringNew(firstLength+secondLength); StringMove(first, new); StringMove(second, new+firstLength); new[firstLength+secondLength]=0; return(new); }; String StringFromNat(number) Nat number; { String string; char stack[32]; Nat nChars=0; Nat i; while (true) { Nat digit=number%10; stack[nChars]=digit+'0'; nChars+=1; if (number<10) break; number=number/10; }; string=StringNew(nChars); for (i=0; ifirst=item; new->rest=list; return(new); }; Nat ListLength(list) List list; { Nat length=0; while (list!=nil) { length+=1; list=list->rest; }; return(length); }; Bool ListEnumerate(list, each, context) List list; ListItemProc each; Ref context; { Bool quit=false; while (list!=nil) { if (quit=each(list->first, context)) break; list=list->rest; }; return(quit); }; Bool ListMemberString(list, candidate) ListOfString list; String candidate; { while (list!=nil) { if (StringEqual(list->first, candidate)) return(true); list=list->rest; }; return(false); }; /* Property */ Property PropertyCreate(rest, key, value) Property rest; Atom key; Ref value; { Property property; property=New(Property, PropertyRec); property->rest=rest; property->key=key; property->value=value; return(property); }; Nat uniqueID=0; String *propertyNames; PropertyPrintProc *propertyPrintProcs; Atom PropertyRegister(name, printProc) String name; PropertyPrintProc printProc; { PropertyPrintProc *newPrintProcs; String *newPropNames; Nat i; newPropNames=(String *)malloc((uniqueID+1)*sizeof(String)); newPrintProcs=(PropertyPrintProc *)malloc((uniqueID+1)*sizeof(PropertyPrintProc)); for (i=0; ikey==property) return(from->value); from=from->rest; }; return(nil); }; Properties PropertyPut(on, property, value) Properties on; Atom property; Ref value; { Properties scan=on; Properties trail=nil; while (scan) { if (scan->key==property) { if (value==nil) { if (trail==nil) return(on->rest); trail->rest=scan->rest; return(on); }; scan->value=value; return(on); }; trail=scan; scan=scan->rest; }; if (value!=nil) return(PropertyCreate(on, property, value)); else return(on); }; void PropertyPrint(properties, indent, cr, level) Properties properties; Nat indent; Bool cr; Nat level; { Properties scan=properties; while (scan) { Nat index=(Nat)scan->key; if (propertyPrintProcs[index]!=nil) (propertyPrintProcs[index])(scan->key, scan->value, indent, level, cr); scan=scan->rest; }; }; void PropertyPrintString(property, value, indent, level, cr) Atom property; Ref value; Nat indent; Nat level; Bool cr; { level=level; StringPrintIndent(indent, cr); printf("%s: %s", propertyNames[(Nat)property], value); }; /* Hash Table */ Nat HashTableHashString(key) Ref key; { String string=(String)key; Nat hash=0; if (string==nil) return(0); while (true) { if (*string==0) break; hash=hash^(*string); string+=1; if (*string==0) break; hash=hash^((*string)<<8); string+=1; }; return(hash); }; Buckets HashTableBucketsCreate(size) Nat size; { Buckets buckets=NewSeq(Buckets, BucketsRec, Properties, size); Nat i; buckets->size=size; for (i=0; ielements[i]=nil; return(buckets); }; HashTable HashTableCreate(size, hash, equal) Nat size; HashProc hash; EqualProc equal; { HashTable table=New(HashTable, HashTableRec); table->hash=hash; table->equal=equal; table->size=0; table->sizeLimit=size; table->buckets=HashTableBucketsCreate(size); return(table); }; Nat HashTableSize(table) HashTable table; { return(table->size); }; Nat ComputeIndex (table, key) HashTable table; Ref key; { Nat hash; if (table->hash==nil) hash=((Nat)key>>16)^(Nat)key; else hash=table->hash(key); return(hash%table->buckets->size); }; Ref HashTableScan(table, bucket, key) HashTable table; Properties bucket; Ref key; { while (bucket) { if ((table->equal==nil && bucket->key==key) || (table->equal!=nil && table->equal(bucket->key, key))) return(bucket->value); bucket=bucket->rest; }; return(nil); }; Ref HashTableGet(table, key) HashTable table; Ref key; { Nat index=ComputeIndex(table, key); Properties bucket=table->buckets->elements[index]; return(HashTableScan(table, bucket, key)); }; #define PrimeTableSize 14 #define highPrime 32749 Nat primeTable[PrimeTableSize] = {2, 5, 11, 23, 53, 113, 251, 509, 1019, 2039, 4079, 8179, 16369, highPrime}; void HashTablePut(table, key, value) HashTable table; Ref key; Ref value; { Nat index=ComputeIndex(table, key); Properties *bucket = &(table->buckets->elements[index]); Bool found=HashTableScan(table, *bucket, key)!=nil; *bucket=PropertyPut(*bucket, (Atom)key, value); if (found && value==nil) table->size-=1; else if (!found && value!=nil) { table->size+=1; if (table->size > table->sizeLimit) { Buckets oldBuckets=table->buckets; Buckets newBuckets; Nat seek=2*table->buckets->size; Nat newPTI=0; Nat newMod=highPrime; Nat i; if (seek >= highPrime) newPTI=PrimeTableSize-1; else while (true) { newMod=primeTable[newPTI]; if (newMod >= seek) break; newPTI+=1; }; if (newMod=table->buckets->size) {table->sizeLimit=0xFFFFFFFFL; return;}; table->sizeLimit=newMod; newBuckets=HashTableBucketsCreate(newMod); table->buckets=newBuckets; for (i=0; isize; i++) { Property cur=oldBuckets->elements[i]; Property next=nil; while (cur!=nil) { Nat newIndex=ComputeIndex(table, cur->key); next=cur->rest; cur->rest=newBuckets->elements[newIndex]; newBuckets->elements[newIndex]=cur; cur=next; }; if (next!=nil) Die; }; }; }; }; void HashTableFree(table) HashTable table; { }; void HashTableUpdate(table, action, context) HashTable table; HashTableUpdateAction action; Ref context; { Nat i; for (i=0; ibuckets->size; i++) { Properties scan=table->buckets->elements[i]; Properties trail=nil; while (scan) { scan->value=action(scan->key, scan->value, context); if (scan->value==nil) { if (trail==nil) table->buckets->elements[i]=scan->rest; else trail->rest=scan->rest; } else trail=scan; scan=scan->rest; }; }; };