summaryrefslogtreecommitdiff
path: root/MLKArray.m
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <matthias@benkard.de>2008-08-06 20:01:55 +0200
committerMatthias Andreas Benkard <matthias@benkard.de>2008-08-06 20:01:55 +0200
commit30c1591ec870d8ebb7f2d0562c54aa88cd149693 (patch)
tree17b80085eed05606af0ad03911c2b595e6588ce0 /MLKArray.m
parentc2281495f8d2d34cafdc05f4a2fcfe752da4ec6d (diff)
Add class MLKArray.
Diffstat (limited to 'MLKArray.m')
-rw-r--r--MLKArray.m210
1 files changed, 210 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#import "MLKArray.h"
+#import "functions.h"
+#import "util.h"
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSEnumerator.h>
+
+#include <stdio.h>
+#include <search.h>
+
+
+@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