]> err.no Git - sope/blob - sope-core/NGStreams/NGCharBuffer.m
fixed gcc 4.1 warnings
[sope] / sope-core / NGStreams / NGCharBuffer.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #include "NGCharBuffer.h"
23 #include "common.h"
24
25 typedef struct NGCharBufferLA {
26   unichar character;
27   char    isEOF:1;
28   char    isFetched:1;
29 } LA_NGCharBuffer;
30
31 @implementation NGCharBuffer
32
33 + (id)charBufferWithSource:(id<NGTextStream>)_source la:(int)_la {
34   return [[[self alloc] initWithSource:_source la:_la] autorelease];
35 }
36
37 - (id)initWithSource:(id<NGTextStream>)_source la:(int)_la {
38   if ((self = [super initWithSource:_source])) {
39     int size = 0;
40
41     if (_la < 1) {
42       [NSException raise:NSRangeException
43                    format:@"lookahead depth is less than one (%d)", _la];
44     }
45
46     // Find first power of 2 >= to requested size
47     for (size = 2; size < _la; size *=2);
48     
49 #if NeXT_Foundation_LIBRARY
50     self->la = NSZoneMalloc([self zone], sizeof(LA_NGCharBuffer) * size);
51 #else
52     self->la = NSZoneMallocAtomic([self zone],
53                                   sizeof(LA_NGCharBuffer) * size);
54 #endif
55     memset(self->la, 0, sizeof(LA_NGCharBuffer) * size);
56
57     self->bufLen      = size;
58     self->sizeLessOne = self->bufLen - 1;
59     self->headIdx     = 0;
60     self->wasEOF      = NO;
61
62     if ([self->source respondsToSelector:@selector(methodForSelector:)]) {
63       self->readCharacter =
64         [(NSObject *)self->source methodForSelector:@selector(readCharacter)];
65     }
66   }
67   return self;
68 }
69
70 - (id)initWithSource:(id<NGTextStream>)_source {
71   [self release];
72   [self doesNotRecognizeSelector:_cmd];
73   return nil;
74 }
75
76 - (id)init {
77   [self release];
78   [self doesNotRecognizeSelector:_cmd];
79   return nil;
80 }
81
82 #if !LIB_FOUNDATION_BOEHM_GC
83 - (void)dealloc {
84   NSZoneFree([self zone], self->la);
85   self->readCharacter = NULL;
86   [super dealloc];
87 }
88 #endif
89
90 - (unichar)readCharacter {
91   int character = [self la:0];
92   if (character < 1)
93       [[[NGEndOfStreamException alloc] init] raise];
94   [self consume];
95   return character;
96 }
97
98 /* LA */
99
100 - (int)la:(int)_la {
101   int result = -1;
102   int idx    = (_la + self->headIdx) & self->sizeLessOne;
103
104   idx = *(&idx);
105   
106   if (_la > self->sizeLessOne) {
107     [NSException raise:NSRangeException
108                  format:@"tried to look ahead too far (la=%d, max=%d)", 
109                   _la, self->bufLen];
110   }
111   
112   if (self->wasEOF) {
113     result = (!self->la[idx].isFetched || self->la[idx].isEOF)
114       ? -1
115       : self->la[idx].character;
116   }
117   else {
118     if (!self->la[idx].isFetched) {
119       int i;
120
121       *(&i) = 0;
122       while ((i < _la) &&
123              (self->la[(self->headIdx + i) & self->sizeLessOne].isFetched))
124         i++;
125
126       NS_DURING {
127         while (i <= _la) {
128           int     ix        = 0;
129           unichar character = 0;
130
131           if (self->readCharacter == NULL) 
132             character = [self->source readCharacter];
133           else
134             character = (int)self->readCharacter(self->source,
135                                                  @selector(readCharacter));
136           ix = (self->headIdx + i) & self->sizeLessOne;      
137           self->la[ix].character = character;
138           self->la[ix].isFetched = 1;
139           i++;
140         }
141       }
142       NS_HANDLER {
143         if ([localException isKindOfClass:[NGEndOfStreamException class]]) {
144           while (i <= _la) {
145             self->la[(self->headIdx + i) & self->sizeLessOne].isEOF = YES;
146             i++;
147             self->wasEOF = YES;        
148           }
149         }
150         else {
151           [localException raise];
152         }
153       }
154       NS_ENDHANDLER;
155     }
156     result = (self->la[idx].isEOF) ? -1 : self->la[idx].character;
157   }
158   return result;
159 }
160
161 - (void)consume {
162   int idx = self->headIdx & sizeLessOne;
163   
164   if (!(self->la[idx].isFetched))
165     [self la:0];
166
167   self->la[idx].isFetched = 0;
168   self->headIdx++;
169 }
170
171 - (void)consume:(int)_cnt {
172   while (_cnt > 0) {
173     int idx = self->headIdx & sizeLessOne;
174     
175     if (!(self->la[idx].isFetched))
176       [self la:0];
177
178     self->la[idx].isFetched = 0;
179     self->headIdx++;
180     _cnt--;
181   }
182 }
183
184 // description
185
186 - (NSString *)description {
187   return [NSString stringWithFormat:@"<%@[0x%p] source=%@ la=%d",
188                      NSStringFromClass([self class]),
189                      (unsigned)self,
190                      self->source,
191                      self->bufLen
192                    ];
193 }
194
195 @end