From 30c1591ec870d8ebb7f2d0562c54aa88cd149693 Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Wed, 6 Aug 2008 20:01:55 +0200 Subject: Add class MLKArray. --- MLKArray.m | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 MLKArray.m (limited to 'MLKArray.m') diff --git a/MLKArray.m b/MLKArray.m new file mode 100644 index 0000000..995dfa8 --- /dev/null +++ b/MLKArray.m @@ -0,0 +1,210 @@ +/* -*- mode: objc; coding: utf-8 -*- */ +/* Toilet Lisp, a Common Lisp subset for the Étoilé runtime. + * Copyright (C) 2008 Matthias Andreas Benkard. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#import "MLKArray.h" +#import "functions.h" +#import "util.h" + +#import +#import + +#include +#include + + +@implementation MLKArray +-(id) initWithDimensions:(NSArray *)dimensions +{ + NSEnumerator *e; + id el; + + _size = 1; + e = [dimensions objectEnumerator]; + while ((el = [e nextObject])) + { + el = denullify (el); + _size *= MLKIntWithInteger (el); + } + + LASSIGN (_dimensions, [dimensions mutableCopy]); + _data = calloc (_size, sizeof (id)); + _fillPointer = -1; + _displacement = nil; + + return self; +} + +-(id) idAtIndex:(NSUInteger)index +{ + if (index > _size || (_fillPointer != -1 && index > _fillPointer)) + [NSException raise:@"NSRangeException" + format:@"Array index out of bounds"]; + + return _data[index]; +} + +-(void) insertId:(id)anObject atIndex:(NSUInteger)index +{ + _size++; + if (_fillPointer != -1) + _fillPointer++; + + _data = realloc (_data, _size * sizeof (id)); + memmove (_data+index+1, _data+index, _size-index); + _data[index] = anObject; +} + +-(void) removeObjectAtIndex:(NSUInteger)index +{ + _size--; + if (_fillPointer != -1) + _fillPointer--; + + memmove (_data+index, _data+index+1, _size-index-1); + _data = realloc (_data, _size * sizeof (id)); +} + +-(void) replaceIdAtIndex:(NSUInteger)index withId:(id)anObject +{ + _data[index] = anObject; +} + +-(NSUInteger) indexOfObjectIdenticalTo:(id)anObject +{ + return [self indexOfObjectIdenticalTo:anObject + inRange:NSMakeRange(0, _size)]; +} + +static int eq (const void *x, const void *y) +{ + return (x == y ? 0 : 1); +} + +-(NSUInteger) indexOfObjectIdenticalTo:(id)anObject inRange:(NSRange)range +{ + // FIXME: How to treat [NSNull null]? + return ((id*)lfind (anObject, _data + range.location, &range.length, sizeof(id), eq) + - _data); +} + +-(NSUInteger) indexOfObject:(id)anObject +{ + return [self indexOfObject:anObject inRange:NSMakeRange(0, _size)]; +} + +static int equalp (const void *x, const void *y) +{ + // FIXME: Hmm... What about fixnums? What about nil? + return ([(id)x isEqual:(id)y] ? 0 : 1); +} + +-(NSUInteger) indexOfObject:(id)anObject inRange:(NSRange)range +{ + // FIXME: How to treat [NSNull null]? + return ((id*)lfind (anObject, _data + range.location, &range.length, sizeof(id), equalp) + - _data); +} + + +-(void) addId:(id)anObject +{ + [self insertId:anObject atIndex:(_fillPointer == -1 ? _size-1 : _fillPointer-1)]; +} + +-(void) setSize:(int)size ofDimension:(int)dimension +{ + // FIXME: ??? +} + +-(void) setFillPointer:(int)fillPointer +{ + _fillPointer = fillPointer; +} + +-(int) fillPointer +{ + return _fillPointer; +} + +-(void) setDisplacement:(NSArray *)array +{ + LASSIGN (_displacement, array); +} + +-(NSArray *) displacement +{ + return _displacement; +} + +-(NSUInteger) count +{ + return (_fillPointer == -1 ? _size : _fillPointer); +} + +-(id) objectAtIndex:(NSUInteger)index +{ + NS_DURING + { + NS_VALUERETURN (nullify([self idAtIndex:index]), id); + } + NS_HANDLER + { + if ([[localException name] isEqualToString:@"NSRangeException"]) + return nil; + else + [localException raise]; + return nil; + } + NS_ENDHANDLER; +} + +-(void) insertObject:(id)anObject atIndex:(NSUInteger)index +{ + [self insertId:denullify(anObject) atIndex:index]; +} + +-(void) addObject:(id)anObject +{ + [self addId:denullify(anObject)]; +} + +-(void) removeLastObject +{ + if (_fillPointer == -1) + [self removeObjectAtIndex:(_size-1)]; + else if (_fillPointer == 0) + [NSException raise:@"NSRangeException" + format:@"Tried to remove an object from an empty array"]; + else + _fillPointer--; +} + +-(void) replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject +{ + [self replaceIdAtIndex:index withId:anObject]; +} + +-(void) dealloc +{ + free (_data); + LDESTROY (_dimensions); + LDESTROY (_displacement); + [super dealloc]; +} +@end -- cgit v1.2.3