2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
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
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.
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
22 #include "NGCharBuffer.h"
25 typedef struct NGCharBufferLA {
31 @implementation NGCharBuffer
33 + (id)charBufferWithSource:(id<NGTextStream>)_source la:(int)_la {
34 return [[[self alloc] initWithSource:_source la:_la] autorelease];
37 - (id)initWithSource:(id<NGTextStream>)_source la:(int)_la {
38 if ((self = [super initWithSource:_source])) {
42 [NSException raise:NSRangeException
43 format:@"lookahead depth is less than one (%d)", _la];
46 // Find first power of 2 >= to requested size
47 for (size = 2; size < _la; size *=2);
49 #if NeXT_Foundation_LIBRARY
50 self->la = NSZoneMalloc([self zone], sizeof(LA_NGCharBuffer) * size);
52 self->la = NSZoneMallocAtomic([self zone],
53 sizeof(LA_NGCharBuffer) * size);
55 memset(self->la, 0, sizeof(LA_NGCharBuffer) * size);
58 self->sizeLessOne = self->bufLen - 1;
62 if ([self->source respondsToSelector:@selector(methodForSelector:)]) {
64 [(NSObject *)self->source methodForSelector:@selector(readCharacter)];
70 - (id)initWithSource:(id<NGTextStream>)_source {
72 [self doesNotRecognizeSelector:_cmd];
78 [self doesNotRecognizeSelector:_cmd];
82 #if !LIB_FOUNDATION_BOEHM_GC
84 NSZoneFree([self zone], self->la);
85 self->readCharacter = NULL;
90 - (unichar)readCharacter {
91 int character = [self la:0];
93 [[[NGEndOfStreamException alloc] init] raise];
102 int idx = (_la + self->headIdx) & self->sizeLessOne;
106 if (_la > self->sizeLessOne) {
107 [NSException raise:NSRangeException
108 format:@"tried to look ahead too far (la=%d, max=%d)",
113 result = (!self->la[idx].isFetched || self->la[idx].isEOF)
115 : self->la[idx].character;
118 if (!self->la[idx].isFetched) {
123 (self->la[(self->headIdx + i) & self->sizeLessOne].isFetched))
129 unichar character = 0;
131 if (self->readCharacter == NULL)
132 character = [self->source readCharacter];
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;
143 if ([localException isKindOfClass:[NGEndOfStreamException class]]) {
145 self->la[(self->headIdx + i) & self->sizeLessOne].isEOF = YES;
151 [localException raise];
156 result = (self->la[idx].isEOF) ? -1 : self->la[idx].character;
162 int idx = self->headIdx & sizeLessOne;
164 if (!(self->la[idx].isFetched))
167 self->la[idx].isFetched = 0;
171 - (void)consume:(int)_cnt {
173 int idx = self->headIdx & sizeLessOne;
175 if (!(self->la[idx].isFetched))
178 self->la[idx].isFetched = 0;
186 - (NSString *)description {
187 return [NSString stringWithFormat:@"<%@[0x%p] source=%@ la=%d",
188 NSStringFromClass([self class]),