2 Copyright (C) 2000-2003 SKYRIX Software AG
4 This file is part of OGo
6 OGo 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 OGo 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 OGo; see the file COPYING. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 #import "NGMemoryAllocation.h"
27 #define NGStorageSize sizeof(NGBitSetStorage)
28 #define NGBitsPerEntry (NGStorageSize * 8)
29 #define NGByteSize (universe / 8)
31 #define NGTestBit(_x) (((storage[ _x / NGBitsPerEntry ] & \
32 (1 << (_x % NGBitsPerEntry))) == 0) ? NO : YES)
34 @interface NGConcreteBitSetEnumerator : NSEnumerator
37 unsigned int universe;
39 NGBitSetStorage *storage;
41 unsigned int position;
49 @implementation NGBitSet
52 return [[[self alloc] init] autorelease];
54 + (id)bitSetWithCapacity:(unsigned)_capacity {
55 return [[[self alloc] initWithCapacity:_capacity] autorelease];
57 + (id)bitSetWithBitSet:(NGBitSet *)_set {
58 return [[[self alloc] initWithBitSet:_set] autorelease];
61 - (id)initWithCapacity:(unsigned)_capacity {
62 if ((self = [super init])) {
63 self->universe = (_capacity / NGBitsPerEntry + 1) * NGBitsPerEntry;
64 storage = NGMallocAtomic(NGByteSize);
65 memset(storage, 0, NGByteSize);
71 - (id)initWithBitSet:(NGBitSet *)_set {
72 if ((self = [self initWithCapacity:NGBitsPerEntry])) {
73 NSEnumerator *enumerator = [_set objectEnumerator];
76 while ((obj = [enumerator nextObject]))
77 [self addMember:[obj unsignedIntValue]];
84 return [self initWithCapacity:NGBitsPerEntry];
86 - (id)initWithNullTerminatedArray:(unsigned int *)_array {
87 if ((self = [self initWithCapacity:NGBitsPerEntry])) {
89 [self addMember:*_array];
98 NGFree(self->storage);
106 - (void)_expandToInclude:(unsigned int)_element {
107 unsigned int nu = (_element / NGBitsPerEntry + 1) * NGBitsPerEntry;
108 if (nu > self->universe) {
110 storage = (NGBitSetStorage *)NGMallocAtomic(nu / 8);
111 memset(storage, 0, nu / 8);
113 memcpy(storage, old, NGByteSize);
123 - (unsigned int)capacity {
124 return self->universe;
126 - (unsigned int)count {
132 - (BOOL)isMember:(unsigned int)_element {
133 return (_element >= self->universe) ? NO : NGTestBit(_element);
136 - (void)addMember:(unsigned int)_element {
137 register unsigned int subIdxPattern = 1 << (_element % NGBitsPerEntry);
139 if (_element >= self->universe)
140 [self _expandToInclude:_element];
142 if ((storage[ _element / NGBitsPerEntry ] & subIdxPattern) == 0) {
143 storage[ _element / NGBitsPerEntry ] |= subIdxPattern;
147 - (void)addMembersInRange:(NSRange)_range {
148 register unsigned int from = _range.location;
149 register unsigned int to = from + _range.length - 1;
151 if (to >= self->universe)
152 [self _expandToInclude:to];
154 for (; from <= to; from++) {
155 register unsigned int subIdxPattern = 1 << (from % NGBitsPerEntry);
157 if ((storage[ from / NGBitsPerEntry ] & subIdxPattern) == 0) {
158 storage[ from / NGBitsPerEntry ] |= subIdxPattern;
164 - (void)addMembersFromBitSet:(NGBitSet *)_set {
167 if ([_set capacity] > self->universe)
168 [self _expandToInclude:[_set capacity]];
170 for (i = 0; i < [_set capacity]; i++) {
171 if ([_set isMember:i]) {
172 register unsigned int subIdxPattern = 1 << (i % NGBitsPerEntry);
174 if ((storage[ i / NGBitsPerEntry ] & subIdxPattern) == 0) {
175 storage[ i / NGBitsPerEntry ] |= subIdxPattern;
182 - (void)removeMember:(unsigned int)_element {
183 register unsigned int subIdxPattern = 1 << (_element % NGBitsPerEntry);
185 if (_element >= self->universe)
188 if ((storage[ _element / NGBitsPerEntry ] & subIdxPattern) != 0) {
189 storage[ _element / NGBitsPerEntry ] -= subIdxPattern;
193 - (void)removeMembersInRange:(NSRange)_range {
194 register unsigned int from = _range.location;
195 register unsigned int to = from + _range.length - 1;
197 if (from >= self->universe)
199 if (to >= self->universe) to = self->universe - 1;
201 for (; from <= to; from++) {
202 register unsigned int subIdxPattern = 1 << (from % NGBitsPerEntry);
204 if ((storage[ from / NGBitsPerEntry ] & subIdxPattern) != 0) {
205 storage[ from / NGBitsPerEntry ] -= subIdxPattern;
210 - (void)removeAllMembers {
211 memset(storage, 0, NGByteSize);
215 - (unsigned int)firstMember {
216 register unsigned int element;
218 for (element = 0; element < self->universe; element++) {
219 if (NGTestBit(element))
225 - (unsigned int)lastMember {
226 register unsigned int element;
228 for (element = (self->universe - 1); element >= 0; element--) {
229 if (NGTestBit(element))
237 - (BOOL)isEqual:(id)_object {
238 if (self == _object) return YES;
239 if ([self class] != [_object class]) return NO;
240 return [self isEqualToSet:_object];
242 - (BOOL)isEqualToSet:(NGBitSet *)_set {
243 if (self == _set) return YES;
244 if (count != [_set count]) return NO;
247 register unsigned int element;
249 for (element = 0; element < self->universe; element++) {
250 if (NGTestBit(element)) {
251 if (![_set isMember:element])
261 - (NSEnumerator *)objectEnumerator {
262 if (self->count == 0)
265 NGConcreteBitSetEnumerator *en = [[NGConcreteBitSetEnumerator alloc] init];
266 en->universe = self->universe;
267 en->count = self->count;
268 en->storage = self->storage;
269 return [en autorelease];
276 return [self copyWithZone:[self zone]];
278 - (id)copyWithZone:(NSZone *)_zone {
279 return [[NGBitSet alloc] initWithBitSet:self];
285 - (void)encodeWithCoder:(NSCoder *)_coder {
286 unsigned int element;
287 register unsigned int found;
289 [_coder encodeValueOfObjCType:@encode(unsigned int) at:&count];
291 for (element = 0, found = 0; (element < self->universe) && (found < count); element++) {
292 if (NGTestBit(element)) {
293 [_coder encodeValueOfObjCType:@encode(unsigned int) at:&element];
298 - (id)initWithCoder:(NSCoder *)_coder {
299 if ((self = [super init])) {
301 register unsigned int cnt;
303 self->universe = NGBitsPerEntry;
304 storage = NGMallocAtomic(NGByteSize);
305 memset(storage, 0, NGByteSize);
307 [_coder decodeValueOfObjCType:@encode(unsigned int) at:&nc];
309 for (cnt = 0; cnt < nc; cnt++) {
311 [_coder decodeValueOfObjCType:@encode(unsigned int) at:&member];
312 [self addMember:member];
320 - (NSString *)description {
321 return [NSString stringWithFormat:
322 @"<NGBitSet[0x%08X]: capacity=%u count=%u content=%@>",
323 (unsigned)self, self->universe, self->count,
324 [[self toArray] description]];
327 - (NSArray *)toArray {
328 NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:count + 1];
329 register unsigned int element, found;
331 for (element = 0, found = 0;
332 (element < self->universe) && (found < self->count); element++) {
334 if (NGTestBit(element)) {
335 [result addObject:[NSNumber numberWithUnsignedInt:element]];
339 return [[[result autorelease] copy] autorelease];
344 @implementation NGConcreteBitSetEnumerator
347 if (self->found == self->count)
349 if (self->position >= self->universe)
352 while (!NGTestBit(self->position))
358 return [NSNumber numberWithUnsignedInt:(self->position - 1)];
361 @end /* NGConcreteBitSetEnumerator */
363 NSString *stringValueForBitset(unsigned int _set, char _setC, char _unsetC,
368 for (pos = 0; pos < _wide; pos++) {
369 register unsigned int v = (1 << pos);
370 buf[(int)pos] = ((v & _set) == v) ? _setC : _unsetC;
374 return [NSString stringWithCString:buf];
377 void __link_NGExtensions_NGBitSet() {
378 __link_NGExtensions_NGBitSet();