1//
2//  ANTLRHashMap.m
3//  ANTLR
4//
5// Copyright (c) 2010 Alan Condit
6// All rights reserved.
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions
10// are met:
11// 1. Redistributions of source code must retain the above copyright
12//    notice, this list of conditions and the following disclaimer.
13// 2. Redistributions in binary form must reproduce the above copyright
14//    notice, this list of conditions and the following disclaimer in the
15//    documentation and/or other materials provided with the distribution.
16// 3. The name of the author may not be used to endorse or promote products
17//    derived from this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#define SUCCESS (0)
31#define FAILURE (-1)
32
33#import "ANTLRHashMap.h"
34
35static NSInteger itIndex;
36
37/*
38 * Start of ANTLRHashMap
39 */
40@implementation ANTLRHashMap
41
42@synthesize Scope;
43@synthesize LastHash;
44
45+(id)newANTLRHashMap
46{
47    return [[ANTLRHashMap alloc] init];
48}
49
50+(id)newANTLRHashMapWithLen:(NSInteger)aBuffSize
51{
52    return [[ANTLRHashMap alloc] initWithLen:aBuffSize];
53}
54
55-(id)init
56{
57    NSInteger idx;
58    
59    if ((self = [super init]) != nil) {
60        fNext = nil;
61        Scope = 0;
62        ptr = 0;
63        BuffSize = HASHSIZE;
64        buffer = [[NSMutableData dataWithLength:(NSUInteger)BuffSize * sizeof(id)] retain];
65        ptrBuffer = (ANTLRMapElement **) [buffer mutableBytes];
66        if ( fNext != nil ) {
67            Scope = ((ANTLRHashMap *)fNext)->Scope+1;
68            for( idx = 0; idx < BuffSize; idx++ ) {
69                ptrBuffer[idx] = ((ANTLRHashMap *)fNext)->ptrBuffer[idx];
70            }
71        }
72        mode = 0;
73    }
74    return( self );
75}
76
77-(id)initWithLen:(NSInteger)aBuffSize
78{
79    NSInteger idx;
80    
81    if ((self = [super init]) != nil) {
82        fNext = nil;
83        BuffSize = aBuffSize;
84        Scope = 0;
85        ptr = 0;
86        buffer = [[NSMutableData dataWithLength:(NSUInteger)BuffSize * sizeof(id)] retain];
87        ptrBuffer = (ANTLRMapElement **) [buffer mutableBytes];
88        if ( fNext != nil ) {
89            Scope = ((ANTLRHashMap *)fNext)->Scope+1;
90            for( idx = 0; idx < BuffSize; idx++ ) {
91                ptrBuffer[idx] = ((ANTLRHashMap *)fNext)->ptrBuffer[idx];
92            }
93        }
94        mode = 0;
95    }
96    return( self );
97}
98
99-(void)dealloc
100{
101#ifdef DEBUG_DEALLOC
102    NSLog( @"called dealloc in ANTLRHashMap" );
103#endif
104    ANTLRMapElement *tmp, *rtmp;
105    NSInteger idx;
106
107    if ( self.fNext != nil ) {
108        for( idx = 0; idx < BuffSize; idx++ ) {
109            tmp = ptrBuffer[idx];
110            while ( tmp && tmp != [((ANTLRHashMap *)fNext) getptrBufferEntry:idx] ) {
111                rtmp = tmp;
112                // tmp = [tmp getfNext];
113                tmp = (ANTLRMapElement *)tmp.fNext;
114                [rtmp release];
115            }
116        }
117    }
118    if ( buffer ) [buffer release];
119    [super dealloc];
120}
121
122- (NSInteger)count
123{
124    NSInteger aCnt = 0;
125    
126    for (NSInteger i = 0; i < BuffSize; i++) {
127        if ( ptrBuffer[i] != nil ) {
128            aCnt++;
129        }
130    }
131    return aCnt;
132}
133                          
134- (NSInteger) size
135{
136    NSInteger aSize = 0;
137    
138    for (NSInteger i = 0; i < BuffSize; i++) {
139        if ( ptrBuffer[i] != nil ) {
140            aSize += sizeof(id);
141        }
142    }
143    return aSize;
144}
145                                  
146                                  
147-(void)deleteANTLRHashMap:(ANTLRMapElement *)np
148{
149    ANTLRMapElement *tmp, *rtmp;
150    NSInteger idx;
151    
152    if ( self.fNext != nil ) {
153        for( idx = 0; idx < BuffSize; idx++ ) {
154            tmp = ptrBuffer[idx];
155            while ( tmp && tmp != (ANTLRLinkBase *)[((ANTLRHashMap *)fNext) getptrBufferEntry:idx] ) {
156                rtmp = tmp;
157                tmp = [tmp getfNext];
158                [rtmp release];
159            }
160        }
161    }
162}
163
164-(ANTLRHashMap *)PushScope:(ANTLRHashMap **)map
165{
166    NSInteger idx;
167    ANTLRHashMap *htmp;
168    
169    htmp = [ANTLRHashMap newANTLRHashMap];
170    if ( *map != nil ) {
171        ((ANTLRHashMap *)htmp)->fNext = *map;
172        [htmp setScope:[((ANTLRHashMap *)htmp->fNext) getScope]+1];
173        for( idx = 0; idx < BuffSize; idx++ ) {
174            htmp->ptrBuffer[idx] = ((ANTLRHashMap *)htmp->fNext)->ptrBuffer[idx];
175        }
176    }
177    //    gScopeLevel++;
178    *map = htmp;
179    return( htmp );
180}
181
182-(ANTLRHashMap *)PopScope:(ANTLRHashMap **)map
183{
184    NSInteger idx;
185    ANTLRMapElement *tmp;
186    ANTLRHashMap *htmp;
187    
188    htmp = *map;
189    if ( (*map)->fNext != nil ) {
190        *map = (ANTLRHashMap *)htmp->fNext;
191        for( idx = 0; idx < BuffSize; idx++ ) {
192            if ( htmp->ptrBuffer[idx] == nil ||
193                htmp->ptrBuffer[idx] == (*map)->ptrBuffer[idx] ) {
194                break;
195            }
196            tmp = htmp->ptrBuffer[idx];
197            /*
198             * must deal with parms, locals and labels at some point
199             * can not forget the debuggers
200             */
201            htmp->ptrBuffer[idx] = [tmp getfNext];
202            [tmp release];
203        }
204        *map = (ANTLRHashMap *)htmp->fNext;
205        //        gScopeLevel--;
206    }
207    return( htmp );
208}
209
210#ifdef USERDOC
211/*
212 *  HASH        hash entry to get index to table
213 *  NSInteger hash( ANTLRHashMap *self, char *s );
214 *
215 *     Inputs:  char *s             string to find
216 *
217 *     Returns: NSInteger                 hashed value
218 *
219 *  Last Revision 9/03/90
220 */
221#endif
222-(NSInteger)hash:(NSString *)s       /*    form hash value for string s */
223{
224    NSInteger hashval;
225    const char *tmp;
226    
227    tmp = [s cStringUsingEncoding:NSASCIIStringEncoding];
228    for( hashval = 0; *tmp != '\0'; )
229        hashval += *tmp++;
230    self->LastHash = hashval % BuffSize;
231    return( self->LastHash );
232}
233
234#ifdef USERDOC
235/*
236 *  FINDSCOPE  search hashed list for entry
237 *  ANTLRHashMap *findscope( ANTLRHashMap *self, NSInteger scope );
238 *
239 *     Inputs:  NSInteger       scope -- scope level to find
240 *
241 *     Returns: ANTLRHashMap   pointer to ptrBuffer of proper scope level
242 *
243 *  Last Revision 9/03/90
244 */
245#endif
246-(ANTLRHashMap *)findscope:(NSInteger)scope
247{
248    if ( self->Scope == scope ) {
249        return( self );
250    }
251    else if ( fNext ) {
252        return( [((ANTLRHashMap *)fNext) findscope:scope] );
253    }
254    return( nil );              /*   not found      */
255}
256
257#ifdef USERDOC
258/*
259 *  LOOKUP  search hashed list for entry
260 *  ANTLRMapElement *lookup( ANTLRHashMap *self, char *s, NSInteger scope );
261 *
262 *     Inputs:  char     *s          string to find
263 *
264 *     Returns: ANTLRMapElement  *           pointer to entry
265 *
266 *  Last Revision 9/03/90
267 */
268#endif
269-(id)lookup:(NSString *)s Scope:(NSInteger)scope
270{
271    ANTLRMapElement *np;
272    
273    for( np = self->ptrBuffer[[self hash:s]]; np != nil; np = [np getfNext] ) {
274        if ( [s isEqualToString:[np getName]] ) {
275            return( np );        /*   found it       */
276        }
277    }
278    return( nil );              /*   not found      */
279}
280
281#ifdef USERDOC
282/*
283 *  INSTALL search hashed list for entry
284 *  NSInteger install( ANTLRHashMap *self, ANTLRMapElement *sym, NSInteger scope );
285 *
286 *     Inputs:  ANTLRMapElement    *sym   -- symbol ptr to install
287 *              NSInteger         scope -- level to find
288 *
289 *     Returns: Boolean     TRUE   if installed
290 *                          FALSE  if already in table
291 *
292 *  Last Revision 9/03/90
293 */
294#endif
295-(ANTLRMapElement *)install:(ANTLRMapElement *)sym Scope:(NSInteger)scope
296{
297    ANTLRMapElement *np;
298    
299    np = [self lookup:[sym getName] Scope:scope ];
300    if ( np == nil ) {
301        [sym retain];
302        [sym setFNext:self->ptrBuffer[ self->LastHash ]];
303        self->ptrBuffer[ self->LastHash ] = sym;
304        return( self->ptrBuffer[ self->LastHash ] );
305    }
306    return( nil );            /*   not found      */
307}
308
309#ifdef USERDOC
310/*
311 *  RemoveSym  search hashed list for entry
312 *  NSInteger RemoveSym( ANTLRHashMap *self, char *s );
313 *
314 *     Inputs:  char     *s          string to find
315 *
316 *     Returns: NSInteger      indicator of SUCCESS OR FAILURE
317 *
318 *  Last Revision 9/03/90
319 */
320#endif
321-(NSInteger)RemoveSym:(NSString *)s
322{
323    ANTLRMapElement *np, *tmp;
324    NSInteger idx;
325    
326    idx = [self hash:s];
327    for ( tmp = self->ptrBuffer[idx], np = self->ptrBuffer[idx]; np != nil; np = [np getfNext] ) {
328        if ( [s isEqualToString:[np getName]] ) {
329            tmp = [np getfNext];             /* get the next link  */
330            [np release];
331            return( SUCCESS );            /* report SUCCESS     */
332        }
333        tmp = [np getfNext];              //  BAD!!!!!!
334    }
335    return( FAILURE );                    /*   not found      */
336}
337
338-(void)delete_chain:(ANTLRMapElement *)np
339{
340    if ( [np getfNext] != nil )
341        [self delete_chain:[np getfNext]];
342    [np dealloc];
343}
344
345#ifdef DONTUSEYET
346-(NSInteger)bld_symtab:(KW_TABLE *)toknams
347{
348    NSInteger i;
349    ANTLRMapElement *np;
350    
351    for( i = 0; *(toknams[i].name) != '\0'; i++ ) {
352        // install symbol in ptrBuffer
353        np = [ANTLRMapElement newANTLRMapElement:[NSString stringWithFormat:@"%s", toknams[i].name]];
354        //        np->fType = toknams[i].toknum;
355        [self install:np Scope:0];
356    }
357    return( SUCCESS );
358}
359#endif
360
361-(ANTLRMapElement *)getptrBufferEntry:(NSInteger)idx
362{
363    return( ptrBuffer[idx] );
364}
365
366-(ANTLRMapElement **)getptrBuffer
367{
368    return( ptrBuffer );
369}
370
371-(void)setptrBuffer:(ANTLRMapElement *)np Index:(NSInteger)idx
372{
373    if ( idx < BuffSize ) {
374        [np retain];
375        ptrBuffer[idx] = np;
376    }
377}
378
379-(NSInteger)getScope
380{
381    return( Scope );
382}
383
384-(void)setScopeScope:(NSInteger)i
385{
386    Scope = i;
387}
388
389- (ANTLRMapElement *)getTType:(NSString *)name
390{
391    return [self lookup:name Scope:0];
392}
393
394/*
395 * works only for maplist indexed not by name but by TokenNumber
396 */
397- (ANTLRMapElement *)getNameInList:(NSInteger)ttype
398{
399    ANTLRMapElement *np;
400    NSInteger aTType;
401
402    aTType = ttype % BuffSize;
403    for( np = self->ptrBuffer[aTType]; np != nil; np = [np getfNext] ) {
404        if ( [(NSNumber *)np.node integerValue] == ttype ) {
405            return( np );        /*   found it       */
406        }
407    }
408    return( nil );              /*   not found      */
409}
410
411- (ANTLRLinkBase *)getName:(NSString *)name
412{
413    return [self lookup:name Scope:0]; /*  nil if not found      */    
414}
415
416- (void)putNode:(NSString *)name TokenType:(NSInteger)ttype
417{
418    ANTLRMapElement *np;
419    
420    // install symbol in ptrBuffer
421    np = [ANTLRMapElement newANTLRMapElementWithName:[NSString stringWithString:name] Type:ttype];
422    //        np->fType = toknams[i].toknum;
423    [self install:np Scope:0];
424}
425
426- (NSInteger)getMode
427{
428    return mode;
429}
430
431- (void)setMode:(NSInteger)aMode
432{
433    mode = aMode;
434}
435
436- (void) addObject:(id)aRule
437{
438    NSInteger idx;
439
440    idx = [self count];
441    if ( idx >= BuffSize ) {
442        idx %= BuffSize;
443    }
444    ptrBuffer[idx] = aRule;
445}
446
447/* this may have to handle linking into the chain
448 */
449- (void) insertObject:(id)aRule atIndex:(NSInteger)idx
450{
451    if ( idx >= BuffSize ) {
452        idx %= BuffSize;
453    }
454    if ( aRule != ptrBuffer[idx] ) {
455        if ( ptrBuffer[idx] ) [ptrBuffer[idx] release];
456        [aRule retain];
457    }
458    ptrBuffer[idx] = aRule;
459}
460
461- (id)objectAtIndex:(NSInteger)idx
462{
463    if ( idx >= BuffSize ) {
464        idx %= BuffSize;
465    }
466    return ptrBuffer[idx];
467}
468
469/* this will never link into the chain
470 */
471- (void) setObject:(id)aRule atIndex:(NSInteger)idx
472{
473    if ( idx >= BuffSize ) {
474        idx %= BuffSize;
475    }
476    if ( aRule != ptrBuffer[idx] ) {
477        if ( ptrBuffer[idx] ) [ptrBuffer[idx] release];
478        [aRule retain];
479    }
480    ptrBuffer[idx] = aRule;
481}
482
483- (void)putName:(NSString *)name Node:(id)aNode
484{
485    ANTLRMapElement *np;
486    
487    np = [self lookup:name Scope:0 ];
488    if ( np == nil ) {
489        np = [ANTLRMapElement newANTLRMapElementWithName:name Node:aNode];
490        if ( ptrBuffer[LastHash] )
491            [ptrBuffer[LastHash] release];
492        [np retain];
493        np.fNext = ptrBuffer[ LastHash ];
494        ptrBuffer[ LastHash ] = np;
495    }
496    return;    
497}
498
499- (NSEnumerator *)objectEnumerator
500{
501#pragma mark fix this its broken
502    NSEnumerator *anEnumerator;
503
504    itIndex = 0;
505    return anEnumerator;
506}
507
508- (BOOL)hasNext
509{
510    if (self && [self count] < BuffSize-1) {
511        return YES;
512    }
513    return NO;
514}
515
516- (ANTLRMapElement *)nextObject
517{
518    if (self && itIndex < BuffSize-1) {
519        return ptrBuffer[itIndex];
520    }
521    return nil;
522}
523
524@synthesize BuffSize;
525@synthesize count;
526@synthesize ptr;
527@synthesize ptrBuffer;
528@synthesize buffer;
529@end
530