]> err.no Git - sope/blob - Recycler/NGJavaScript/NGJavaScriptArray.m
fixed a warning in resource manager
[sope] / Recycler / NGJavaScript / NGJavaScriptArray.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
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
9   later version.
10
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.
15
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
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include "NGJavaScriptObject.h"
24 #include "NGJavaScriptContext.h"
25 #include "NGJavaScriptObjectMappingContext.h"
26 #include "common.h"
27
28 #define ARCHIVE_AS_NSARRAY 1
29
30 @interface NGJavaScriptArray(Private)
31 - (NSArray *)convertToNSArray;
32 @end
33
34 @implementation NGJavaScriptArray
35
36 + (void)initialize {
37   static BOOL isInitialized = NO;
38   if (!isInitialized) {
39     isInitialized = YES;
40 #if NeXT_RUNTIME || APPLE_RUNTIME || GNUSTEP_BASE_LIBRARY
41     NSLog(@"WARNING(%s): adding NSMutableArray behaviour to "
42           @"NGJavaScriptArray is not supported with the current"
43           @"runtime!", __PRETTY_FUNCTION__);
44     /* TODO: port to MacOSX/GNUstep */
45 #else
46     class_add_behavior(self, [NSMutableArray class]);
47 #endif
48   }
49 }
50
51 - (void *)createJSObjectForJSClass:(void *)_class inJSContext:(void *)jsctx {
52   /* this is called by initWithClassHandle ... */
53   return JS_NewArrayObject(jsctx, 0 /* length */, NULL /* vector */);
54   //return JS_NewObject(jsctx, _class, NULL, NULL);
55 }
56
57 + (void *)jsObjectClass {
58   return &js_ArrayClass;
59 }
60
61 /* convert to array */
62
63 - (NSArray *)convertToNSArray {
64   jsint   i, count;
65   id      *objs;
66   NSArray *array;
67   
68   if (!JS_GetArrayLength(self->jscx, self->handle, &count))
69     return nil;
70   
71   if (count <= 0)
72     return [NSArray array];
73
74   objs = calloc(count, sizeof(id));
75   for (i = 0; i < count; i++) {
76     static id null = nil;
77     jsval val;
78
79     if (null == nil)
80       null = [[NSClassFromString(@"EONull") alloc] init];
81
82     if (!JS_GetElement(self->jscx, self->handle, i, &val))
83       objs[i] = null;
84     else
85       objs[i] = [self->ctx objectForJSValue:&val];
86   }
87   array = [[NSArray alloc] initWithObjects:objs count:count];
88   free(objs);
89   return [array autorelease];
90 }
91
92 - (NSArray *)copyWithZone:(NSZone *)_zone {
93   return [[self convertToNSArray] copyWithZone:_zone];
94 }
95 - (NSMutableArray *)mutableCopyWithZone:(NSZone *)_zone {
96   return [[self convertToNSArray] mutableCopyWithZone:_zone];
97 }
98
99 /* NSCoding */
100
101 #if ARCHIVE_AS_NSARRAY
102
103 - (id)replacementObjectForCoder:(NSCoder*)anEncoder {
104   id array;
105   
106   array = [[[self convertToNSArray] mutableCopy] autorelease];
107   NSLog(@"%s: replace %@ with %@", __PRETTY_FUNCTION__, self, array);
108   return array;
109 }
110 #if 0
111 - (Class)classForCoder {
112   return [NSMutableArray class];
113 }
114 #endif
115 #endif
116
117 - (void)decodeJavaScriptPropertiesWithCoder:(NSCoder *)_coder {
118   unsigned i, count;
119   
120   [_coder decodeValueOfObjCType:@encode(unsigned) at:&count];
121   for (i = 0; i < count; i++) {
122     id obj = [_coder decodeObject];
123     [self addObject:obj];
124   }
125 }
126 - (void)encodeJavaScriptPropertiesWithCoder:(NSCoder *)_coder {
127   unsigned i, count;
128   
129   count = [self count];
130   [_coder encodeValueOfObjCType:@encode(unsigned) at:&count];
131   
132   for (i = 0; i < count; i++)
133     [_coder encodeObject:[self objectAtIndex:i]];
134 }
135
136 /* description */
137
138 - (NSString *)description {
139   return [[self convertToNSArray] description];
140 }
141
142 @end /* NGJavaScriptArray */
143
144 @implementation NGJavaScriptArray(NSArrayCompatibility)
145
146 - (unsigned)count {
147   jsint v;
148   
149   if (JS_GetArrayLength(self->jscx, self->handle, &v))
150     return v;
151   
152   return 0;
153 }
154
155 - (id)objectAtIndex:(unsigned)_idx {
156   jsval obj;
157
158   if (JS_GetElement(self->jscx, self->handle, _idx, &obj))
159     return [self->ctx objectForJSValue:&obj];
160   
161   /* get failed */
162   return nil;
163 }
164
165 - (NSEnumerator *)objectEnumerator {
166   return [[self convertToNSArray] objectEnumerator];
167 }
168
169 - (id)lastObject {
170   jsint v;
171
172   if (JS_GetArrayLength(self->jscx, self->handle, &v)) {
173     jsval obj;
174
175     if (JS_GetElement(self->jscx, self->handle, v, &obj))
176       return [self->ctx objectForJSValue:&obj];
177   }
178   /* failed */
179   return nil;
180 }
181
182 - (BOOL)containsObject:(id)_obj {
183   // to be improved ...
184   return [[self convertToNSArray] containsObject:_obj];
185 }
186
187 /* Deriving New Array */
188
189 - (NSArray *)arrayByAddingObject:(id)anObject {
190   return [[self convertToNSArray] arrayByAddingObject:anObject];
191 }
192 - (NSArray *)arrayByAddingObjectsFromArray:(NSArray *)anotherArray {
193   return [[self convertToNSArray] arrayByAddingObjectsFromArray:anotherArray];
194 }
195
196 - (NSArray *)sortedArrayUsingFunction:
197   (int(*)(id element1, id element2, void *userData))comparator
198   context:(void*)context
199 {
200   return [[self convertToNSArray]
201                 sortedArrayUsingFunction:comparator
202                 context:context];
203 }
204 - (NSArray *)sortedArrayUsingSelector:(SEL)comparator {
205   return [[self convertToNSArray] sortedArrayUsingSelector:comparator];
206 }
207
208 - (NSArray *)subarrayWithRange:(NSRange)_range {
209   // to be improved ...
210   return [[self convertToNSArray] subarrayWithRange:_range];
211 }
212
213 @end /* NGJavaScriptArray(NSArrayCompatibility) */
214
215 @implementation NGJavaScriptArray(NSMutableArrayCompatibility)
216
217 - (void)setObject:(id)_obj atIndex:(unsigned)_idx {
218   jsval obj;
219   
220   if ([self->ctx jsValue:&obj forObject:_obj]) {
221     if (JS_SetElement(self->jscx, self->handle, _idx, &obj))
222       // ok
223       return;
224   }
225   
226   NSAssert2(NO, @"set element failed (%@ at idx %d) !", self, _idx);
227 }
228
229 static inline void
230 _removeObjectsFrom(NGJavaScriptArray *self,
231                    unsigned int _idx, unsigned int _count)
232 {
233   jsint i, itemsCount;
234
235 #if 0
236   /* cannot use DeleteElement ! this doesn't adjust indizes !! */
237   NSAssert(JS_DeleteElement(self->jscx, self->handle, _idx),
238            @"delete-element failed in JS");
239 #endif
240   
241   if (_count == 0)
242     return;
243   if (!JS_GetArrayLength(self->jscx, self->handle, &itemsCount))
244     goto failed;
245   if ((_idx + _count) > itemsCount)
246     goto failed;
247
248   /* move to front */
249   for (i = (_idx + _count); i < itemsCount; i++, _idx++) {
250     jsval val;
251     
252     if (!JS_GetElement(self->jscx, self->handle, i, &val))
253       goto failed;
254     
255     if (!JS_SetElement(self->jscx, self->handle, _idx, &val))
256       goto failed;
257   }
258   
259   /* shorten array */
260   if (JS_SetArrayLength(self->jscx, self->handle, itemsCount - _count)) {
261     /* ok */
262     return;
263   }
264   
265  failed:
266   NSCAssert3(NO, @"element remove failed (%@ at idx %d,%d) !",
267              self, _idx, _count);
268 }
269
270 - (void)removeObjectsInRange:(NSRange)aRange {
271   _removeObjectsFrom(self, aRange.location, aRange.length);
272 }
273 - (void)removeAllObjects {
274   _removeObjectsFrom(self, 0, [self count]);
275 }
276 - (void)removeLastObject {
277   unsigned itemsCount;
278   itemsCount = [self count];
279   if (itemsCount > 0) _removeObjectsFrom(self, (itemsCount - 1), 1);
280 }
281 - (void)removeObjectAtIndex:(unsigned)_idx {
282   _removeObjectsFrom(self, _idx, 1);
283 }
284
285 - (void)insertObject:(id)_object atIndex:(unsigned)_idx {
286   jsval obj;
287   jsint i, itemsCount;
288
289 #if 0
290   NSLog(@"%s: before: %@", __PRETTY_FUNCTION__,
291         [[[self convertToNSArray]
292                 valueForKey:@"description"]
293                 componentsJoinedByString:@","]);
294 #endif
295   
296   if (!JS_GetArrayLength(self->jscx, self->handle, &itemsCount))
297     goto failed;
298   
299   if (_idx > itemsCount)
300     /* range exception ... */
301     goto failed;
302   
303   /* move items up */
304   for (i = itemsCount; i > _idx; i--) {
305     jsval val;
306     
307     if (!JS_GetElement(self->jscx, self->handle, (i - 1), &val))
308       goto failed;
309     
310     if (!JS_SetElement(self->jscx, self->handle, i, &val))
311       goto failed;
312   }
313   
314   /* get JS value of new object */
315   if (![self->ctx jsValue:&obj forObject:_object])
316     goto failed;
317   
318   /* place new item */
319   if (JS_SetElement(self->jscx, self->handle, _idx, &obj)) {
320     /* ok */
321 #if 0
322     NSLog(@"%s: after: %@", __PRETTY_FUNCTION__,
323           [[[self convertToNSArray]
324                   valueForKey:@"description"]
325                   componentsJoinedByString:@","]);
326 #endif
327     return;
328   }
329   
330  failed:
331   NSAssert2(NO, @"element insert failed (%@ at idx %d) !", self, _idx);
332 }
333 - (void)addObject:(id)_object {
334   [self insertObject:_object atIndex:[self count]];
335 }
336
337 @end /* NGJavaScriptArray(NSMutableArrayCompatibility) */