summary refs log tree commit diff stats
path: root/libs/cocos2d/Support
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cocos2d/Support')
-rwxr-xr-xlibs/cocos2d/Support/CCArray.h106
-rwxr-xr-xlibs/cocos2d/Support/CCArray.m290
-rwxr-xr-xlibs/cocos2d/Support/CCFileUtils.h62
-rwxr-xr-xlibs/cocos2d/Support/CCFileUtils.m169
-rwxr-xr-xlibs/cocos2d/Support/CCProfiling.h53
-rwxr-xr-xlibs/cocos2d/Support/CCProfiling.m117
-rwxr-xr-xlibs/cocos2d/Support/CGPointExtension.h334
-rwxr-xr-xlibs/cocos2d/Support/CGPointExtension.m196
-rwxr-xr-xlibs/cocos2d/Support/OpenGL_Internal.h80
-rwxr-xr-xlibs/cocos2d/Support/TGAlib.h55
-rwxr-xr-xlibs/cocos2d/Support/TGAlib.m274
-rwxr-xr-xlibs/cocos2d/Support/TransformUtils.h37
-rwxr-xr-xlibs/cocos2d/Support/TransformUtils.m46
-rwxr-xr-xlibs/cocos2d/Support/ZipUtils.h91
-rwxr-xr-xlibs/cocos2d/Support/ZipUtils.m251
-rwxr-xr-xlibs/cocos2d/Support/base64.c93
-rwxr-xr-xlibs/cocos2d/Support/base64.h33
-rwxr-xr-xlibs/cocos2d/Support/ccCArray.h447
-rwxr-xr-xlibs/cocos2d/Support/ccUtils.c20
-rwxr-xr-xlibs/cocos2d/Support/ccUtils.h29
-rwxr-xr-xlibs/cocos2d/Support/uthash.h972
-rwxr-xr-xlibs/cocos2d/Support/utlist.h490
22 files changed, 4245 insertions, 0 deletions
diff --git a/libs/cocos2d/Support/CCArray.h b/libs/cocos2d/Support/CCArray.h new file mode 100755 index 0000000..0c7b2b8 --- /dev/null +++ b/libs/cocos2d/Support/CCArray.h
@@ -0,0 +1,106 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 ForzeField Studios S.L. http://forzefield.com
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25
26#import "ccCArray.h"
27
28
29/** A faster alternative of NSArray.
30 CCArray uses internally a c-array.
31 @since v0.99.4
32 */
33
34
35/** @def CCARRAY_FOREACH
36 A convience macro to iterate over a CCArray using. It is faster than the "fast enumeration" interface.
37 @since v0.99.4
38 */
39
40#define CCARRAY_FOREACH(__array__, __object__) \
41if (__array__ && __array__->data->num > 0) \
42for(id *__arr__ = __array__->data->arr, *end = __array__->data->arr + __array__->data->num-1; \
43 __arr__ <= end && ((__object__ = *__arr__) != nil || true); \
44 __arr__++)
45
46@interface CCArray : NSObject <NSFastEnumeration, NSCoding, NSCopying>
47{
48 @public ccArray *data;
49}
50
51+ (id) array;
52+ (id) arrayWithCapacity:(NSUInteger)capacity;
53+ (id) arrayWithArray:(CCArray*)otherArray;
54+ (id) arrayWithNSArray:(NSArray*)otherArray;
55
56
57- (id) initWithCapacity:(NSUInteger)capacity;
58- (id) initWithArray:(CCArray*)otherArray;
59- (id) initWithNSArray:(NSArray*)otherArray;
60
61
62// Querying an Array
63
64- (NSUInteger) count;
65- (NSUInteger) capacity;
66- (NSUInteger) indexOfObject:(id)object;
67- (id) objectAtIndex:(NSUInteger)index;
68- (BOOL) containsObject:(id)object;
69- (id) randomObject;
70- (id) lastObject;
71- (NSArray*) getNSArray;
72
73
74// Adding Objects
75
76- (void) addObject:(id)object;
77- (void) addObjectsFromArray:(CCArray*)otherArray;
78- (void) addObjectsFromNSArray:(NSArray*)otherArray;
79- (void) insertObject:(id)object atIndex:(NSUInteger)index;
80
81
82// Removing Objects
83
84- (void) removeLastObject;
85- (void) removeObject:(id)object;
86- (void) removeObjectAtIndex:(NSUInteger)index;
87- (void) removeObjectsInArray:(CCArray*)otherArray;
88- (void) removeAllObjects;
89- (void) fastRemoveObject:(id)object;
90- (void) fastRemoveObjectAtIndex:(NSUInteger)index;
91
92
93// Rearranging Content
94
95- (void) exchangeObject:(id)object1 withObject:(id)object2;
96- (void) exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2;
97- (void) reverseObjects;
98- (void) reduceMemoryFootprint;
99
100// Sending Messages to Elements
101
102- (void) makeObjectsPerformSelector:(SEL)aSelector;
103- (void) makeObjectsPerformSelector:(SEL)aSelector withObject:(id)object;
104
105
106@end
diff --git a/libs/cocos2d/Support/CCArray.m b/libs/cocos2d/Support/CCArray.m new file mode 100755 index 0000000..a48a5f3 --- /dev/null +++ b/libs/cocos2d/Support/CCArray.m
@@ -0,0 +1,290 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 ForzeField Studios S.L. http://forzefield.com
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#import "CCArray.h"
26#import "../ccMacros.h"
27
28
29@implementation CCArray
30
31+ (id) array
32{
33 return [[[self alloc] init] autorelease];
34}
35
36+ (id) arrayWithCapacity:(NSUInteger)capacity
37{
38 return [[[self alloc] initWithCapacity:capacity] autorelease];
39}
40
41+ (id) arrayWithArray:(CCArray*)otherArray
42{
43 return [[(CCArray*)[self alloc] initWithArray:otherArray] autorelease];
44}
45
46+ (id) arrayWithNSArray:(NSArray*)otherArray
47{
48 return [[(CCArray*)[self alloc] initWithNSArray:otherArray] autorelease];
49}
50
51- (id) init
52{
53 self = [self initWithCapacity:2];
54 return self;
55}
56
57- (id) initWithCapacity:(NSUInteger)capacity
58{
59 self = [super init];
60 if (self != nil) {
61 data = ccArrayNew(capacity);
62 }
63 return self;
64}
65
66- (id) initWithArray:(CCArray*)otherArray
67{
68 self = [self initWithCapacity:otherArray->data->num];
69 if (self != nil) {
70 [self addObjectsFromArray:otherArray];
71 }
72 return self;
73}
74
75- (id) initWithNSArray:(NSArray*)otherArray
76{
77 self = [self initWithCapacity:otherArray.count];
78 if (self != nil) {
79 [self addObjectsFromNSArray:otherArray];
80 }
81 return self;
82}
83
84- (id) initWithCoder:(NSCoder*)coder
85{
86 self = [self initWithNSArray:[coder decodeObjectForKey:@"nsarray"]];
87 return self;
88}
89
90
91#pragma mark Querying an Array
92
93- (NSUInteger) count
94{
95 return data->num;
96}
97
98- (NSUInteger) capacity
99{
100 return data->max;
101}
102
103- (NSUInteger) indexOfObject:(id)object
104{
105 return ccArrayGetIndexOfObject(data, object);
106}
107
108- (id) objectAtIndex:(NSUInteger)index
109{
110 NSAssert2( index < data->num, @"index out of range in objectAtIndex(%d), index %i", data->num, index );
111
112 return data->arr[index];
113}
114
115- (BOOL) containsObject:(id)object
116{
117 return ccArrayContainsObject(data, object);
118}
119
120- (id) lastObject
121{
122 if( data->num > 0 )
123 return data->arr[data->num-1];
124 return nil;
125}
126
127- (id) randomObject
128{
129 if(data->num==0) return nil;
130 return data->arr[(int)(data->num*CCRANDOM_0_1())];
131}
132
133- (NSArray*) getNSArray
134{
135 return [NSArray arrayWithObjects:data->arr count:data->num];
136}
137
138
139#pragma mark Adding Objects
140
141- (void) addObject:(id)object
142{
143 ccArrayAppendObjectWithResize(data, object);
144}
145
146- (void) addObjectsFromArray:(CCArray*)otherArray
147{
148 ccArrayAppendArrayWithResize(data, otherArray->data);
149}
150
151- (void) addObjectsFromNSArray:(NSArray*)otherArray
152{
153 ccArrayEnsureExtraCapacity(data, otherArray.count);
154 for(id object in otherArray)
155 ccArrayAppendObject(data, object);
156}
157
158- (void) insertObject:(id)object atIndex:(NSUInteger)index
159{
160 ccArrayInsertObjectAtIndex(data, object, index);
161}
162
163
164#pragma mark Removing Objects
165
166- (void) removeObject:(id)object
167{
168 ccArrayRemoveObject(data, object);
169}
170
171- (void) removeObjectAtIndex:(NSUInteger)index
172{
173 ccArrayRemoveObjectAtIndex(data, index);
174}
175
176- (void) fastRemoveObject:(id)object
177{
178 ccArrayFastRemoveObject(data, object);
179}
180
181- (void) fastRemoveObjectAtIndex:(NSUInteger)index
182{
183 ccArrayFastRemoveObjectAtIndex(data, index);
184}
185
186- (void) removeObjectsInArray:(CCArray*)otherArray
187{
188 ccArrayRemoveArray(data, otherArray->data);
189}
190
191- (void) removeLastObject
192{
193 NSAssert( data->num > 0, @"no objects added" );
194
195 ccArrayRemoveObjectAtIndex(data, data->num-1);
196}
197
198- (void) removeAllObjects
199{
200 ccArrayRemoveAllObjects(data);
201}
202
203
204#pragma mark Rearranging Content
205
206- (void) exchangeObject:(id)object1 withObject:(id)object2
207{
208 NSUInteger index1 = ccArrayGetIndexOfObject(data, object1);
209 if(index1 == NSNotFound) return;
210 NSUInteger index2 = ccArrayGetIndexOfObject(data, object2);
211 if(index2 == NSNotFound) return;
212
213 ccArraySwapObjectsAtIndexes(data, index1, index2);
214}
215
216- (void) exchangeObjectAtIndex:(NSUInteger)index1 withObjectAtIndex:(NSUInteger)index2
217{
218 ccArraySwapObjectsAtIndexes(data, index1, index2);
219}
220
221- (void) reverseObjects
222{
223 if (data->num > 1)
224 {
225 //floor it since in case of a oneven number the number of swaps stays the same
226 int count = (int) floorf(data->num/2.f);
227 NSUInteger maxIndex = data->num - 1;
228
229 for (int i = 0; i < count ; i++)
230 {
231 ccArraySwapObjectsAtIndexes(data, i, maxIndex);
232 maxIndex--;
233 }
234 }
235}
236
237- (void) reduceMemoryFootprint
238{
239 ccArrayShrink(data);
240}
241
242#pragma mark Sending Messages to Elements
243
244- (void) makeObjectsPerformSelector:(SEL)aSelector
245{
246 ccArrayMakeObjectsPerformSelector(data, aSelector);
247}
248
249- (void) makeObjectsPerformSelector:(SEL)aSelector withObject:(id)object
250{
251 ccArrayMakeObjectsPerformSelectorWithObject(data, aSelector, object);
252}
253
254
255#pragma mark CCArray - NSFastEnumeration protocol
256
257- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
258{
259 if(state->state == 1) return 0;
260
261 state->mutationsPtr = (unsigned long *)self;
262 state->itemsPtr = &data->arr[0];
263 state->state = 1;
264 return data->num;
265}
266
267
268#pragma mark CCArray - NSCopying protocol
269
270- (id)copyWithZone:(NSZone *)zone
271{
272 NSArray *nsArray = [self getNSArray];
273 CCArray *newArray = [[[self class] allocWithZone:zone] initWithNSArray:nsArray];
274 return newArray;
275}
276
277- (void) encodeWithCoder:(NSCoder *)coder
278{
279 [coder encodeObject:[self getNSArray] forKey:@"nsarray"];
280}
281
282#pragma mark
283
284- (void) dealloc
285{
286 ccArrayFree(data);
287 [super dealloc];
288}
289
290@end
diff --git a/libs/cocos2d/Support/CCFileUtils.h b/libs/cocos2d/Support/CCFileUtils.h new file mode 100755 index 0000000..0455202 --- /dev/null +++ b/libs/cocos2d/Support/CCFileUtils.h
@@ -0,0 +1,62 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import <Foundation/Foundation.h>
29
30
31/** Helper class to handle file operations */
32@interface CCFileUtils : NSObject
33{
34}
35
36/** Returns the fullpath of an filename.
37
38 If this method is when Retina Display is enabled, then the
39 Retina Display suffix will be appended to the file (See ccConfig.h).
40
41 If the Retina Display image doesn't exist, then it will return the "non-Retina Display" image
42
43 */
44+(NSString*) fullPathFromRelativePath:(NSString*) relPath;
45@end
46
47/** loads a file into memory.
48 the caller should release the allocated buffer.
49
50 @returns the size of the allocated buffer
51 @since v0.99.5
52 */
53NSInteger ccLoadFileIntoMemory(const char *filename, unsigned char **out);
54
55
56/** removes the HD suffix from a path
57
58 @returns NSString * without the HD suffix
59 @since v0.99.5
60 */
61NSString *ccRemoveHDSuffixFromFile( NSString *path );
62
diff --git a/libs/cocos2d/Support/CCFileUtils.m b/libs/cocos2d/Support/CCFileUtils.m new file mode 100755 index 0000000..6d33799 --- /dev/null +++ b/libs/cocos2d/Support/CCFileUtils.m
@@ -0,0 +1,169 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2008-2010 Ricardo Quesada
5 * Copyright (c) 2011 Zynga Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 *
25 */
26
27
28#import <Availability.h>
29#import "CCFileUtils.h"
30#import "../CCConfiguration.h"
31#import "../ccMacros.h"
32#import "../ccConfig.h"
33
34static NSFileManager *__localFileManager=nil;
35
36//
37NSInteger ccLoadFileIntoMemory(const char *filename, unsigned char **out)
38{
39 NSCAssert( out, @"ccLoadFileIntoMemory: invalid 'out' parameter");
40 NSCAssert( &*out, @"ccLoadFileIntoMemory: invalid 'out' parameter");
41
42 size_t size = 0;
43 FILE *f = fopen(filename, "rb");
44 if( !f ) {
45 *out = NULL;
46 return -1;
47 }
48
49 fseek(f, 0, SEEK_END);
50 size = ftell(f);
51 fseek(f, 0, SEEK_SET);
52
53 *out = malloc(size);
54 size_t read = fread(*out, 1, size, f);
55 if( read != size ) {
56 free(*out);
57 *out = NULL;
58 return -1;
59 }
60
61 fclose(f);
62
63 return size;
64}
65
66NSString *ccRemoveHDSuffixFromFile( NSString *path )
67{
68#if CC_IS_RETINA_DISPLAY_SUPPORTED
69
70 if( CC_CONTENT_SCALE_FACTOR() == 2 ) {
71
72 NSString *name = [path lastPathComponent];
73
74 // check if path already has the suffix.
75 if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {
76
77 CCLOG(@"cocos2d: Filename(%@) contains %@ suffix. Removing it. See cocos2d issue #1040", path, CC_RETINA_DISPLAY_FILENAME_SUFFIX);
78
79 NSString *newLastname = [name stringByReplacingOccurrencesOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX withString:@""];
80
81 NSString *pathWithoutLastname = [path stringByDeletingLastPathComponent];
82 return [pathWithoutLastname stringByAppendingPathComponent:newLastname];
83 }
84 }
85
86#endif // CC_IS_RETINA_DISPLAY_SUPPORTED
87
88 return path;
89
90}
91
92
93@implementation CCFileUtils
94
95+(void) initialize
96{
97 if( self == [CCFileUtils class] )
98 __localFileManager = [[NSFileManager alloc] init];
99}
100
101+(NSString*) getDoubleResolutionImage:(NSString*)path
102{
103#if CC_IS_RETINA_DISPLAY_SUPPORTED
104
105 if( CC_CONTENT_SCALE_FACTOR() == 2 )
106 {
107
108 NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
109 NSString *name = [pathWithoutExtension lastPathComponent];
110
111 // check if path already has the suffix.
112 if( [name rangeOfString:CC_RETINA_DISPLAY_FILENAME_SUFFIX].location != NSNotFound ) {
113
114 CCLOG(@"cocos2d: WARNING Filename(%@) already has the suffix %@. Using it.", name, CC_RETINA_DISPLAY_FILENAME_SUFFIX);
115 return path;
116 }
117
118
119 NSString *extension = [path pathExtension];
120
121 if( [extension isEqualToString:@"ccz"] || [extension isEqualToString:@"gz"] )
122 {
123 // All ccz / gz files should be in the format filename.xxx.ccz
124 // so we need to pull off the .xxx part of the extension as well
125 extension = [NSString stringWithFormat:@"%@.%@", [pathWithoutExtension pathExtension], extension];
126 pathWithoutExtension = [pathWithoutExtension stringByDeletingPathExtension];
127 }
128
129
130 NSString *retinaName = [pathWithoutExtension stringByAppendingString:CC_RETINA_DISPLAY_FILENAME_SUFFIX];
131 retinaName = [retinaName stringByAppendingPathExtension:extension];
132
133 if( [__localFileManager fileExistsAtPath:retinaName] )
134 return retinaName;
135
136 CCLOG(@"cocos2d: CCFileUtils: Warning HD file not found: %@", [retinaName lastPathComponent] );
137 }
138
139#endif // CC_IS_RETINA_DISPLAY_SUPPORTED
140
141 return path;
142}
143
144+(NSString*) fullPathFromRelativePath:(NSString*) relPath
145{
146 NSAssert(relPath != nil, @"CCFileUtils: Invalid path");
147
148 NSString *fullpath = nil;
149
150 // only if it is not an absolute path
151 if( ! [relPath isAbsolutePath] )
152 {
153 NSString *file = [relPath lastPathComponent];
154 NSString *imageDirectory = [relPath stringByDeletingLastPathComponent];
155
156 fullpath = [[NSBundle mainBundle] pathForResource:file
157 ofType:nil
158 inDirectory:imageDirectory];
159 }
160
161 if (fullpath == nil)
162 fullpath = relPath;
163
164 fullpath = [self getDoubleResolutionImage:fullpath];
165
166 return fullpath;
167}
168
169@end
diff --git a/libs/cocos2d/Support/CCProfiling.h b/libs/cocos2d/Support/CCProfiling.h new file mode 100755 index 0000000..b241fb9 --- /dev/null +++ b/libs/cocos2d/Support/CCProfiling.h
@@ -0,0 +1,53 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Stuart Carnie
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import <Foundation/Foundation.h>
28#import <sys/time.h>
29
30@class CCProfilingTimer;
31
32@interface CCProfiler : NSObject {
33 NSMutableArray* activeTimers;
34}
35
36+ (CCProfiler*)sharedProfiler;
37+ (CCProfilingTimer*)timerWithName:(NSString*)timerName andInstance:(id)instance;
38+ (void)releaseTimer:(CCProfilingTimer*)timer;
39- (void)displayTimers;
40
41@end
42
43
44@interface CCProfilingTimer : NSObject {
45 NSString* name;
46 struct timeval startTime;
47 double averageTime;
48}
49
50@end
51
52extern void CCProfilingBeginTimingBlock(CCProfilingTimer* timer);
53extern void CCProfilingEndTimingBlock(CCProfilingTimer* timer);
diff --git a/libs/cocos2d/Support/CCProfiling.m b/libs/cocos2d/Support/CCProfiling.m new file mode 100755 index 0000000..13c8c81 --- /dev/null +++ b/libs/cocos2d/Support/CCProfiling.m
@@ -0,0 +1,117 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2010 Stuart Carnie
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import "../ccConfig.h"
27
28#if CC_ENABLE_PROFILERS
29
30#import "CCProfiling.h"
31
32@interface CCProfilingTimer()
33- (id)initWithName:(NSString*)timerName andInstance:(id)instance;
34@end
35
36@implementation CCProfiler
37
38static CCProfiler* g_sharedProfiler;
39
40+ (CCProfiler*)sharedProfiler {
41 if (!g_sharedProfiler)
42 g_sharedProfiler = [[CCProfiler alloc] init];
43
44 return g_sharedProfiler;
45}
46
47+ (CCProfilingTimer*)timerWithName:(NSString*)timerName andInstance:(id)instance {
48 CCProfiler* p = [CCProfiler sharedProfiler];
49 CCProfilingTimer* t = [[CCProfilingTimer alloc] initWithName:timerName andInstance:instance];
50 [p->activeTimers addObject:t];
51 [t release];
52 return t;
53}
54
55+ (void)releaseTimer:(CCProfilingTimer*)timer {
56 CCProfiler* p = [CCProfiler sharedProfiler];
57 [p->activeTimers removeObject:timer];
58}
59
60- (id)init {
61 if (!(self = [super init])) return nil;
62
63 activeTimers = [[NSMutableArray alloc] init];
64
65 return self;
66}
67
68- (void)dealloc {
69 [activeTimers release];
70 [super dealloc];
71}
72
73- (void)displayTimers {
74 for (id timer in activeTimers) {
75 printf("%s\n", [[timer description] cStringUsingEncoding:[NSString defaultCStringEncoding]]);
76 }
77}
78
79@end
80
81@implementation CCProfilingTimer
82
83- (id)initWithName:(NSString*)timerName andInstance:(id)instance {
84 if (!(self = [super init])) return nil;
85
86 name = [[NSString stringWithFormat:@"%@ (0x%.8x)", timerName, instance] retain];
87
88 return self;
89}
90
91- (void)dealloc {
92 [name release];
93 [super dealloc];
94}
95
96- (NSString*)description {
97 return [NSString stringWithFormat:@"%@ : avg time, %fms", name, averageTime];
98}
99
100void CCProfilingBeginTimingBlock(CCProfilingTimer* timer) {
101 gettimeofday(&timer->startTime, NULL);
102}
103
104typedef unsigned int uint32;
105void CCProfilingEndTimingBlock(CCProfilingTimer* timer) {
106 struct timeval currentTime;
107 gettimeofday(&currentTime, NULL);
108 timersub(&currentTime, &timer->startTime, &currentTime);
109 double duration = currentTime.tv_sec * 1000.0 + currentTime.tv_usec / 1000.0;
110
111 // return in milliseconds
112 timer->averageTime = (timer->averageTime + duration) / 2.0f;
113}
114
115@end
116
117#endif
diff --git a/libs/cocos2d/Support/CGPointExtension.h b/libs/cocos2d/Support/CGPointExtension.h new file mode 100755 index 0000000..96edeb7 --- /dev/null +++ b/libs/cocos2d/Support/CGPointExtension.h
@@ -0,0 +1,334 @@
1/* cocos2d for iPhone
2 * http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2007 Scott Lembcke
5 *
6 * Copyright (c) 2010 Lam Pham
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27/*
28 * Some of the functions were based on Chipmunk's cpVect.h.
29 */
30
31/**
32 @file
33 CGPoint extensions based on Chipmunk's cpVect file.
34 These extensions work both with CGPoint and cpVect.
35
36 The "ccp" prefix means: "CoCos2d Point"
37
38 Examples:
39 - ccpAdd( ccp(1,1), ccp(2,2) ); // preferred cocos2d way
40 - ccpAdd( CGPointMake(1,1), CGPointMake(2,2) ); // also ok but more verbose
41
42 - cpvadd( cpv(1,1), cpv(2,2) ); // way of the chipmunk
43 - ccpAdd( cpv(1,1), cpv(2,2) ); // mixing chipmunk and cocos2d (avoid)
44 - cpvadd( CGPointMake(1,1), CGPointMake(2,2) ); // mixing chipmunk and CG (avoid)
45 */
46
47#import <Availability.h>
48
49#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
50#import <CoreGraphics/CGGeometry.h>
51#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
52#import <Foundation/Foundation.h>
53#endif
54
55#import <math.h>
56#import <objc/objc.h>
57
58#ifdef __cplusplus
59extern "C" {
60#endif
61
62/** Helper macro that creates a CGPoint
63 @return CGPoint
64 @since v0.7.2
65 */
66#define ccp(__X__,__Y__) CGPointMake(__X__,__Y__)
67
68
69/** Returns opposite of point.
70 @return CGPoint
71 @since v0.7.2
72 */
73static inline CGPoint
74ccpNeg(const CGPoint v)
75{
76 return ccp(-v.x, -v.y);
77}
78
79/** Calculates sum of two points.
80 @return CGPoint
81 @since v0.7.2
82 */
83static inline CGPoint
84ccpAdd(const CGPoint v1, const CGPoint v2)
85{
86 return ccp(v1.x + v2.x, v1.y + v2.y);
87}
88
89/** Calculates difference of two points.
90 @return CGPoint
91 @since v0.7.2
92 */
93static inline CGPoint
94ccpSub(const CGPoint v1, const CGPoint v2)
95{
96 return ccp(v1.x - v2.x, v1.y - v2.y);
97}
98
99/** Returns point multiplied by given factor.
100 @return CGPoint
101 @since v0.7.2
102 */
103static inline CGPoint
104ccpMult(const CGPoint v, const CGFloat s)
105{
106 return ccp(v.x*s, v.y*s);
107}
108
109/** Calculates midpoint between two points.
110 @return CGPoint
111 @since v0.7.2
112 */
113static inline CGPoint
114ccpMidpoint(const CGPoint v1, const CGPoint v2)
115{
116 return ccpMult(ccpAdd(v1, v2), 0.5f);
117}
118
119/** Calculates dot product of two points.
120 @return CGFloat
121 @since v0.7.2
122 */
123static inline CGFloat
124ccpDot(const CGPoint v1, const CGPoint v2)
125{
126 return v1.x*v2.x + v1.y*v2.y;
127}
128
129/** Calculates cross product of two points.
130 @return CGFloat
131 @since v0.7.2
132 */
133static inline CGFloat
134ccpCross(const CGPoint v1, const CGPoint v2)
135{
136 return v1.x*v2.y - v1.y*v2.x;
137}
138
139/** Calculates perpendicular of v, rotated 90 degrees counter-clockwise -- cross(v, perp(v)) >= 0
140 @return CGPoint
141 @since v0.7.2
142 */
143static inline CGPoint
144ccpPerp(const CGPoint v)
145{
146 return ccp(-v.y, v.x);
147}
148
149/** Calculates perpendicular of v, rotated 90 degrees clockwise -- cross(v, rperp(v)) <= 0
150 @return CGPoint
151 @since v0.7.2
152 */
153static inline CGPoint
154ccpRPerp(const CGPoint v)
155{
156 return ccp(v.y, -v.x);
157}
158
159/** Calculates the projection of v1 over v2.
160 @return CGPoint
161 @since v0.7.2
162 */
163static inline CGPoint
164ccpProject(const CGPoint v1, const CGPoint v2)
165{
166 return ccpMult(v2, ccpDot(v1, v2)/ccpDot(v2, v2));
167}
168
169/** Rotates two points.
170 @return CGPoint
171 @since v0.7.2
172 */
173static inline CGPoint
174ccpRotate(const CGPoint v1, const CGPoint v2)
175{
176 return ccp(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x);
177}
178
179/** Unrotates two points.
180 @return CGPoint
181 @since v0.7.2
182 */
183static inline CGPoint
184ccpUnrotate(const CGPoint v1, const CGPoint v2)
185{
186 return ccp(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y);
187}
188
189/** Calculates the square length of a CGPoint (not calling sqrt() )
190 @return CGFloat
191 @since v0.7.2
192 */
193static inline CGFloat
194ccpLengthSQ(const CGPoint v)
195{
196 return ccpDot(v, v);
197}
198
199/** Calculates distance between point an origin
200 @return CGFloat
201 @since v0.7.2
202 */
203CGFloat ccpLength(const CGPoint v);
204
205/** Calculates the distance between two points
206 @return CGFloat
207 @since v0.7.2
208 */
209CGFloat ccpDistance(const CGPoint v1, const CGPoint v2);
210
211/** Returns point multiplied to a length of 1.
212 @return CGPoint
213 @since v0.7.2
214 */
215CGPoint ccpNormalize(const CGPoint v);
216
217/** Converts radians to a normalized vector.
218 @return CGPoint
219 @since v0.7.2
220 */
221CGPoint ccpForAngle(const CGFloat a);
222
223/** Converts a vector to radians.
224 @return CGFloat
225 @since v0.7.2
226 */
227CGFloat ccpToAngle(const CGPoint v);
228
229
230/** Clamp a value between from and to.
231 @since v0.99.1
232 */
233float clampf(float value, float min_inclusive, float max_inclusive);
234
235/** Clamp a point between from and to.
236 @since v0.99.1
237 */
238CGPoint ccpClamp(CGPoint p, CGPoint from, CGPoint to);
239
240/** Quickly convert CGSize to a CGPoint
241 @since v0.99.1
242 */
243CGPoint ccpFromSize(CGSize s);
244
245/** Run a math operation function on each point component
246 * absf, fllorf, ceilf, roundf
247 * any function that has the signature: float func(float);
248 * For example: let's try to take the floor of x,y
249 * ccpCompOp(p,floorf);
250 @since v0.99.1
251 */
252CGPoint ccpCompOp(CGPoint p, float (*opFunc)(float));
253
254/** Linear Interpolation between two points a and b
255 @returns
256 alpha == 0 ? a
257 alpha == 1 ? b
258 otherwise a value between a..b
259 @since v0.99.1
260 */
261CGPoint ccpLerp(CGPoint a, CGPoint b, float alpha);
262
263
264/** @returns if points have fuzzy equality which means equal with some degree of variance.
265 @since v0.99.1
266 */
267BOOL ccpFuzzyEqual(CGPoint a, CGPoint b, float variance);
268
269
270/** Multiplies a nd b components, a.x*b.x, a.y*b.y
271 @returns a component-wise multiplication
272 @since v0.99.1
273 */
274CGPoint ccpCompMult(CGPoint a, CGPoint b);
275
276/** @returns the signed angle in radians between two vector directions
277 @since v0.99.1
278 */
279float ccpAngleSigned(CGPoint a, CGPoint b);
280
281/** @returns the angle in radians between two vector directions
282 @since v0.99.1
283*/
284float ccpAngle(CGPoint a, CGPoint b);
285
286/** Rotates a point counter clockwise by the angle around a pivot
287 @param v is the point to rotate
288 @param pivot is the pivot, naturally
289 @param angle is the angle of rotation cw in radians
290 @returns the rotated point
291 @since v0.99.1
292 */
293CGPoint ccpRotateByAngle(CGPoint v, CGPoint pivot, float angle);
294
295/** A general line-line intersection test
296 @param p1
297 is the startpoint for the first line P1 = (p1 - p2)
298 @param p2
299 is the endpoint for the first line P1 = (p1 - p2)
300 @param p3
301 is the startpoint for the second line P2 = (p3 - p4)
302 @param p4
303 is the endpoint for the second line P2 = (p3 - p4)
304 @param s
305 is the range for a hitpoint in P1 (pa = p1 + s*(p2 - p1))
306 @param t
307 is the range for a hitpoint in P3 (pa = p2 + t*(p4 - p3))
308 @return bool
309 indicating successful intersection of a line
310 note that to truly test intersection for segments we have to make
311 sure that s & t lie within [0..1] and for rays, make sure s & t > 0
312 the hit point is p3 + t * (p4 - p3);
313 the hit point also is p1 + s * (p2 - p1);
314 @since v0.99.1
315 */
316BOOL ccpLineIntersect(CGPoint p1, CGPoint p2,
317 CGPoint p3, CGPoint p4,
318 float *s, float *t);
319
320/*
321 ccpSegmentIntersect returns YES if Segment A-B intersects with segment C-D
322 @since v1.0.0
323 */
324BOOL ccpSegmentIntersect(CGPoint A, CGPoint B, CGPoint C, CGPoint D);
325
326/*
327 ccpIntersectPoint returns the intersection point of line A-B, C-D
328 @since v1.0.0
329 */
330CGPoint ccpIntersectPoint(CGPoint A, CGPoint B, CGPoint C, CGPoint D);
331
332#ifdef __cplusplus
333}
334#endif
diff --git a/libs/cocos2d/Support/CGPointExtension.m b/libs/cocos2d/Support/CGPointExtension.m new file mode 100755 index 0000000..b06859d --- /dev/null +++ b/libs/cocos2d/Support/CGPointExtension.m
@@ -0,0 +1,196 @@
1/* cocos2d for iPhone
2 * http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2007 Scott Lembcke
5 *
6 * Copyright (c) 2010 Lam Pham
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27#include "stdio.h"
28#include "math.h"
29
30#import "../ccMacros.h" // CC_SWAP
31#include "CGPointExtension.h"
32
33#define kCGPointEpsilon FLT_EPSILON
34
35CGFloat
36ccpLength(const CGPoint v)
37{
38 return sqrtf(ccpLengthSQ(v));
39}
40
41CGFloat
42ccpDistance(const CGPoint v1, const CGPoint v2)
43{
44 return ccpLength(ccpSub(v1, v2));
45}
46
47CGPoint
48ccpNormalize(const CGPoint v)
49{
50 return ccpMult(v, 1.0f/ccpLength(v));
51}
52
53CGPoint
54ccpForAngle(const CGFloat a)
55{
56 return ccp(cosf(a), sinf(a));
57}
58
59CGFloat
60ccpToAngle(const CGPoint v)
61{
62 return atan2f(v.y, v.x);
63}
64
65CGPoint ccpLerp(CGPoint a, CGPoint b, float alpha)
66{
67 return ccpAdd(ccpMult(a, 1.f - alpha), ccpMult(b, alpha));
68}
69
70float clampf(float value, float min_inclusive, float max_inclusive)
71{
72 if (min_inclusive > max_inclusive) {
73 CC_SWAP(min_inclusive,max_inclusive);
74 }
75 return value < min_inclusive ? min_inclusive : value < max_inclusive? value : max_inclusive;
76}
77
78CGPoint ccpClamp(CGPoint p, CGPoint min_inclusive, CGPoint max_inclusive)
79{
80 return ccp(clampf(p.x,min_inclusive.x,max_inclusive.x), clampf(p.y, min_inclusive.y, max_inclusive.y));
81}
82
83CGPoint ccpFromSize(CGSize s)
84{
85 return ccp(s.width, s.height);
86}
87
88CGPoint ccpCompOp(CGPoint p, float (*opFunc)(float))
89{
90 return ccp(opFunc(p.x), opFunc(p.y));
91}
92
93BOOL ccpFuzzyEqual(CGPoint a, CGPoint b, float var)
94{
95 if(a.x - var <= b.x && b.x <= a.x + var)
96 if(a.y - var <= b.y && b.y <= a.y + var)
97 return true;
98 return false;
99}
100
101CGPoint ccpCompMult(CGPoint a, CGPoint b)
102{
103 return ccp(a.x * b.x, a.y * b.y);
104}
105
106float ccpAngleSigned(CGPoint a, CGPoint b)
107{
108 CGPoint a2 = ccpNormalize(a);
109 CGPoint b2 = ccpNormalize(b);
110 float angle = atan2f(a2.x * b2.y - a2.y * b2.x, ccpDot(a2, b2));
111 if( fabs(angle) < kCGPointEpsilon ) return 0.f;
112 return angle;
113}
114
115CGPoint ccpRotateByAngle(CGPoint v, CGPoint pivot, float angle)
116{
117 CGPoint r = ccpSub(v, pivot);
118 float cosa = cosf(angle), sina = sinf(angle);
119 float t = r.x;
120 r.x = t*cosa - r.y*sina + pivot.x;
121 r.y = t*sina + r.y*cosa + pivot.y;
122 return r;
123}
124
125
126BOOL ccpSegmentIntersect(CGPoint A, CGPoint B, CGPoint C, CGPoint D)
127{
128 float S, T;
129
130 if( ccpLineIntersect(A, B, C, D, &S, &T )
131 && (S >= 0.0f && S <= 1.0f && T >= 0.0f && T <= 1.0f) )
132 return YES;
133
134 return NO;
135}
136
137CGPoint ccpIntersectPoint(CGPoint A, CGPoint B, CGPoint C, CGPoint D)
138{
139 float S, T;
140
141 if( ccpLineIntersect(A, B, C, D, &S, &T) ) {
142 // Point of intersection
143 CGPoint P;
144 P.x = A.x + S * (B.x - A.x);
145 P.y = A.y + S * (B.y - A.y);
146 return P;
147 }
148
149 return CGPointZero;
150}
151
152BOOL ccpLineIntersect(CGPoint A, CGPoint B,
153 CGPoint C, CGPoint D,
154 float *S, float *T)
155{
156 // FAIL: Line undefined
157 if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) ) return NO;
158
159 const float BAx = B.x - A.x;
160 const float BAy = B.y - A.y;
161 const float DCx = D.x - C.x;
162 const float DCy = D.y - C.y;
163 const float ACx = A.x - C.x;
164 const float ACy = A.y - C.y;
165
166 const float denom = DCy*BAx - DCx*BAy;
167
168 *S = DCx*ACy - DCy*ACx;
169 *T = BAx*ACy - BAy*ACx;
170
171 if (denom == 0) {
172 if (*S == 0 || *T == 0) {
173 // Lines incident
174 return YES;
175 }
176 // Lines parallel and not incident
177 return NO;
178 }
179
180 *S = *S / denom;
181 *T = *T / denom;
182
183 // Point of intersection
184 // CGPoint P;
185 // P.x = A.x + *S * (B.x - A.x);
186 // P.y = A.y + *S * (B.y - A.y);
187
188 return YES;
189}
190
191float ccpAngle(CGPoint a, CGPoint b)
192{
193 float angle = acosf(ccpDot(ccpNormalize(a), ccpNormalize(b)));
194 if( fabs(angle) < kCGPointEpsilon ) return 0.f;
195 return angle;
196}
diff --git a/libs/cocos2d/Support/OpenGL_Internal.h b/libs/cocos2d/Support/OpenGL_Internal.h new file mode 100755 index 0000000..4789683 --- /dev/null +++ b/libs/cocos2d/Support/OpenGL_Internal.h
@@ -0,0 +1,80 @@
1/*
2
3===== IMPORTANT =====
4
5This is sample code demonstrating API, technology or techniques in development.
6Although this sample code has been reviewed for technical accuracy, it is not
7final. Apple is supplying this information to help you plan for the adoption of
8the technologies and programming interfaces described herein. This information
9is subject to change, and software implemented based on this sample code should
10be tested with final operating system software and final documentation. Newer
11versions of this sample code may be provided with future seeds of the API or
12technology. For information about updates to this and other developer
13documentation, view the New & Updated sidebars in subsequent documentation
14seeds.
15
16=====================
17
18File: OpenGL_Internal.h
19Abstract: This file is included for support purposes and isn't necessary for
20understanding this sample.
21
22Version: 1.0
23
24Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
25("Apple") in consideration of your agreement to the following terms, and your
26use, installation, modification or redistribution of this Apple software
27constitutes acceptance of these terms. If you do not agree with these terms,
28please do not use, install, modify or redistribute this Apple software.
29
30In consideration of your agreement to abide by the following terms, and subject
31to these terms, Apple grants you a personal, non-exclusive license, under
32Apple's copyrights in this original Apple software (the "Apple Software"), to
33use, reproduce, modify and redistribute the Apple Software, with or without
34modifications, in source and/or binary forms; provided that if you redistribute
35the Apple Software in its entirety and without modifications, you must retain
36this notice and the following text and disclaimers in all such redistributions
37of the Apple Software.
38Neither the name, trademarks, service marks or logos of Apple Inc. may be used
39to endorse or promote products derived from the Apple Software without specific
40prior written permission from Apple. Except as expressly stated in this notice,
41no other rights or licenses, express or implied, are granted by Apple herein,
42including but not limited to any patent rights that may be infringed by your
43derivative works or by other works in which the Apple Software may be
44incorporated.
45
46The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
47WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
48WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
50COMBINATION WITH YOUR PRODUCTS.
51
52IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
53CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
54GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
56DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
57CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
58APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59
60Copyright (C) 2008 Apple Inc. All Rights Reserved.
61
62*/
63
64/* Generic error reporting */
65#define REPORT_ERROR(__FORMAT__, ...) printf("%s: %s\n", __FUNCTION__, [[NSString stringWithFormat:__FORMAT__, __VA_ARGS__] UTF8String])
66
67/* EAGL and GL functions calling wrappers that log on error */
68#define CALL_EAGL_FUNCTION(__FUNC__, ...) ({ EAGLError __error = __FUNC__( __VA_ARGS__ ); if(__error != kEAGLErrorSuccess) printf("%s() called from %s returned error %i\n", #__FUNC__, __FUNCTION__, __error); (__error ? NO : YES); })
69//#define CHECK_GL_ERROR() ({ GLenum __error = glGetError(); if(__error) printf("OpenGL error 0x%04X in %s\n", __error, __FUNCTION__); (__error ? NO : YES); })
70#define CHECK_GL_ERROR() ({ GLenum __error = glGetError(); if(__error) printf("OpenGL error 0x%04X in %s\n", __error, __FUNCTION__); })
71
72/* Optional delegate methods support */
73#ifndef __DELEGATE_IVAR__
74#define __DELEGATE_IVAR__ _delegate
75#endif
76#ifndef __DELEGATE_METHODS_IVAR__
77#define __DELEGATE_METHODS_IVAR__ _delegateMethods
78#endif
79#define TEST_DELEGATE_METHOD_BIT(__BIT__) (self->__DELEGATE_METHODS_IVAR__ & (1 << __BIT__))
80#define SET_DELEGATE_METHOD_BIT(__BIT__, __NAME__) { if([self->__DELEGATE_IVAR__ respondsToSelector:@selector(__NAME__)]) self->__DELEGATE_METHODS_IVAR__ |= (1 << __BIT__); else self->__DELEGATE_METHODS_IVAR__ &= ~(1 << __BIT__); }
diff --git a/libs/cocos2d/Support/TGAlib.h b/libs/cocos2d/Support/TGAlib.h new file mode 100755 index 0000000..247084e --- /dev/null +++ b/libs/cocos2d/Support/TGAlib.h
@@ -0,0 +1,55 @@
1//
2// TGA lib for cocos2d-iphone
3//
4// sources from: http://www.lighthouse3d.com/opengl/terrain/index.php3?tgasource
5//
6
7//#ifndef TGA_LIB
8//#define TGA_LIB
9
10/**
11 @file
12 TGA image support
13 */
14
15enum {
16 TGA_OK,
17 TGA_ERROR_FILE_OPEN,
18 TGA_ERROR_READING_FILE,
19 TGA_ERROR_INDEXED_COLOR,
20 TGA_ERROR_MEMORY,
21 TGA_ERROR_COMPRESSED_FILE,
22};
23
24/** TGA format */
25typedef struct sImageTGA {
26 int status;
27 unsigned char type, pixelDepth;
28
29 /** map width */
30 short int width;
31
32 /** map height */
33 short int height;
34
35 /** raw data */
36 unsigned char *imageData;
37 int flipped;
38} tImageTGA;
39
40/// load the image header fields. We only keep those that matter!
41void tgaLoadHeader(FILE *file, tImageTGA *info);
42
43/// loads the image pixels. You shouldn't call this function directly
44void tgaLoadImageData(FILE *file, tImageTGA *info);
45
46/// this is the function to call when we want to load an image
47tImageTGA * tgaLoad(const char *filename);
48
49// /converts RGB to greyscale
50void tgaRGBtogreyscale(tImageTGA *info);
51
52/// releases the memory used for the image
53void tgaDestroy(tImageTGA *info);
54
55//#endif // TGA_LIB
diff --git a/libs/cocos2d/Support/TGAlib.m b/libs/cocos2d/Support/TGAlib.m new file mode 100755 index 0000000..11303b4 --- /dev/null +++ b/libs/cocos2d/Support/TGAlib.m
@@ -0,0 +1,274 @@
1//
2// TGA lib for cocos2d-iphone
3//
4// sources from: http://www.lighthouse3d.com/opengl/terrain/index.php3?tgasource
5//
6// TGA RLE compression support by Ernesto Corvi
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#import "TGAlib.h"
13
14void tgaLoadRLEImageData(FILE *file, tImageTGA *info);
15void tgaFlipImage( tImageTGA *info );
16
17// load the image header fields. We only keep those that matter!
18void tgaLoadHeader(FILE *file, tImageTGA *info) {
19 unsigned char cGarbage;
20 short int iGarbage;
21
22 fread(&cGarbage, sizeof(unsigned char), 1, file);
23 fread(&cGarbage, sizeof(unsigned char), 1, file);
24
25 // type must be 2 or 3
26 fread(&info->type, sizeof(unsigned char), 1, file);
27
28 fread(&iGarbage, sizeof(short int), 1, file);
29 fread(&iGarbage, sizeof(short int), 1, file);
30 fread(&cGarbage, sizeof(unsigned char), 1, file);
31 fread(&iGarbage, sizeof(short int), 1, file);
32 fread(&iGarbage, sizeof(short int), 1, file);
33
34 fread(&info->width, sizeof(short int), 1, file);
35 fread(&info->height, sizeof(short int), 1, file);
36 fread(&info->pixelDepth, sizeof(unsigned char), 1, file);
37
38 fread(&cGarbage, sizeof(unsigned char), 1, file);
39
40 info->flipped = 0;
41 if ( cGarbage & 0x20 ) info->flipped = 1;
42}
43
44// loads the image pixels. You shouldn't call this function directly
45void tgaLoadImageData(FILE *file, tImageTGA *info) {
46
47 int mode,total,i;
48 unsigned char aux;
49
50 // mode equal the number of components for each pixel
51 mode = info->pixelDepth / 8;
52 // total is the number of unsigned chars we'll have to read
53 total = info->height * info->width * mode;
54
55 fread(info->imageData,sizeof(unsigned char),total,file);
56
57 // mode=3 or 4 implies that the image is RGB(A). However TGA
58 // stores it as BGR(A) so we'll have to swap R and B.
59 if (mode >= 3)
60 for (i=0; i < total; i+= mode) {
61 aux = info->imageData[i];
62 info->imageData[i] = info->imageData[i+2];
63 info->imageData[i+2] = aux;
64 }
65}
66
67// loads the RLE encoded image pixels. You shouldn't call this function directly
68void tgaLoadRLEImageData(FILE *file, tImageTGA *info)
69{
70 unsigned int mode,total,i, index = 0;
71 unsigned char aux[4], runlength = 0;
72 unsigned int skip = 0, flag = 0;
73
74 // mode equal the number of components for each pixel
75 mode = info->pixelDepth / 8;
76 // total is the number of unsigned chars we'll have to read
77 total = info->height * info->width;
78
79 for( i = 0; i < total; i++ )
80 {
81 // if we have a run length pending, run it
82 if ( runlength != 0 )
83 {
84 // we do, update the run length count
85 runlength--;
86 skip = (flag != 0);
87 }
88 else
89 {
90 // otherwise, read in the run length token
91 if ( fread(&runlength,sizeof(unsigned char),1,file) != 1 )
92 return;
93
94 // see if it's a RLE encoded sequence
95 flag = runlength & 0x80;
96 if ( flag ) runlength -= 128;
97 skip = 0;
98 }
99
100 // do we need to skip reading this pixel?
101 if ( !skip )
102 {
103 // no, read in the pixel data
104 if ( fread(aux,sizeof(unsigned char),mode,file) != mode )
105 return;
106
107 // mode=3 or 4 implies that the image is RGB(A). However TGA
108 // stores it as BGR(A) so we'll have to swap R and B.
109 if ( mode >= 3 )
110 {
111 unsigned char tmp;
112
113 tmp = aux[0];
114 aux[0] = aux[2];
115 aux[2] = tmp;
116 }
117 }
118
119 // add the pixel to our image
120 memcpy(&info->imageData[index], aux, mode);
121 index += mode;
122 }
123}
124
125void tgaFlipImage( tImageTGA *info )
126{
127 // mode equal the number of components for each pixel
128 int mode = info->pixelDepth / 8;
129 int rowbytes = info->width*mode;
130 unsigned char *row = (unsigned char *)malloc(rowbytes);
131 int y;
132
133 if (row == NULL) return;
134
135 for( y = 0; y < (info->height/2); y++ )
136 {
137 memcpy(row, &info->imageData[y*rowbytes],rowbytes);
138 memcpy(&info->imageData[y*rowbytes], &info->imageData[(info->height-(y+1))*rowbytes], rowbytes);
139 memcpy(&info->imageData[(info->height-(y+1))*rowbytes], row, rowbytes);
140 }
141
142 free(row);
143 info->flipped = 0;
144}
145
146// this is the function to call when we want to load an image
147tImageTGA * tgaLoad(const char *filename) {
148
149 FILE *file;
150 tImageTGA *info;
151 int mode,total;
152
153 // allocate memory for the info struct and check!
154 info = (tImageTGA *)malloc(sizeof(tImageTGA));
155 if (info == NULL)
156 return(NULL);
157
158
159 // open the file for reading (binary mode)
160 file = fopen(filename, "rb");
161 if (file == NULL) {
162 info->status = TGA_ERROR_FILE_OPEN;
163 return(info);
164 }
165
166 // load the header
167 tgaLoadHeader(file,info);
168
169 // check for errors when loading the header
170 if (ferror(file)) {
171 info->status = TGA_ERROR_READING_FILE;
172 fclose(file);
173 return(info);
174 }
175
176 // check if the image is color indexed
177 if (info->type == 1) {
178 info->status = TGA_ERROR_INDEXED_COLOR;
179 fclose(file);
180 return(info);
181 }
182 // check for other types (compressed images)
183 if ((info->type != 2) && (info->type !=3) && (info->type !=10) ) {
184 info->status = TGA_ERROR_COMPRESSED_FILE;
185 fclose(file);
186 return(info);
187 }
188
189 // mode equals the number of image components
190 mode = info->pixelDepth / 8;
191 // total is the number of unsigned chars to read
192 total = info->height * info->width * mode;
193 // allocate memory for image pixels
194 info->imageData = (unsigned char *)malloc(sizeof(unsigned char) *
195 total);
196
197 // check to make sure we have the memory required
198 if (info->imageData == NULL) {
199 info->status = TGA_ERROR_MEMORY;
200 fclose(file);
201 return(info);
202 }
203 // finally load the image pixels
204 if ( info->type == 10 )
205 tgaLoadRLEImageData(file, info);
206 else
207 tgaLoadImageData(file,info);
208
209 // check for errors when reading the pixels
210 if (ferror(file)) {
211 info->status = TGA_ERROR_READING_FILE;
212 fclose(file);
213 return(info);
214 }
215 fclose(file);
216 info->status = TGA_OK;
217
218 if ( info->flipped )
219 {
220 tgaFlipImage( info );
221 if ( info->flipped ) info->status = TGA_ERROR_MEMORY;
222 }
223
224 return(info);
225}
226
227// converts RGB to greyscale
228void tgaRGBtogreyscale(tImageTGA *info) {
229
230 int mode,i,j;
231
232 unsigned char *newImageData;
233
234 // if the image is already greyscale do nothing
235 if (info->pixelDepth == 8)
236 return;
237
238 // compute the number of actual components
239 mode = info->pixelDepth / 8;
240
241 // allocate an array for the new image data
242 newImageData = (unsigned char *)malloc(sizeof(unsigned char) *
243 info->height * info->width);
244 if (newImageData == NULL) {
245 return;
246 }
247
248 // convert pixels: greyscale = o.30 * R + 0.59 * G + 0.11 * B
249 for (i = 0,j = 0; j < info->width * info->height; i +=mode, j++)
250 newImageData[j] =
251 (unsigned char)(0.30 * info->imageData[i] +
252 0.59 * info->imageData[i+1] +
253 0.11 * info->imageData[i+2]);
254
255
256 //free old image data
257 free(info->imageData);
258
259 // reassign pixelDepth and type according to the new image type
260 info->pixelDepth = 8;
261 info->type = 3;
262 // reassing imageData to the new array.
263 info->imageData = newImageData;
264}
265
266// releases the memory used for the image
267void tgaDestroy(tImageTGA *info) {
268
269 if (info != NULL) {
270 if (info->imageData != NULL)
271 free(info->imageData);
272 free(info);
273 }
274}
diff --git a/libs/cocos2d/Support/TransformUtils.h b/libs/cocos2d/Support/TransformUtils.h new file mode 100755 index 0000000..49fde35 --- /dev/null +++ b/libs/cocos2d/Support/TransformUtils.h
@@ -0,0 +1,37 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26#import <Availability.h>
27
28#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
29#import <UIKit/UIKit.h>
30#import <OpenGLES/ES1/gl.h>
31#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
32#import <OpenGL/gl.h>
33#import <Foundation/Foundation.h>
34#endif
35
36void CGAffineToGL(const CGAffineTransform *t, GLfloat *m);
37void GLToCGAffine(const GLfloat *m, CGAffineTransform *t);
diff --git a/libs/cocos2d/Support/TransformUtils.m b/libs/cocos2d/Support/TransformUtils.m new file mode 100755 index 0000000..9caecf0 --- /dev/null +++ b/libs/cocos2d/Support/TransformUtils.m
@@ -0,0 +1,46 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 * Copyright (c) 2009 Valentin Milea
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26
27#import "TransformUtils.h"
28
29void CGAffineToGL(const CGAffineTransform *t, GLfloat *m)
30{
31 // | m[0] m[4] m[8] m[12] | | m11 m21 m31 m41 | | a c 0 tx |
32 // | m[1] m[5] m[9] m[13] | | m12 m22 m32 m42 | | b d 0 ty |
33 // | m[2] m[6] m[10] m[14] | <=> | m13 m23 m33 m43 | <=> | 0 0 1 0 |
34 // | m[3] m[7] m[11] m[15] | | m14 m24 m34 m44 | | 0 0 0 1 |
35
36 m[2] = m[3] = m[6] = m[7] = m[8] = m[9] = m[11] = m[14] = 0.0f;
37 m[10] = m[15] = 1.0f;
38 m[0] = t->a; m[4] = t->c; m[12] = t->tx;
39 m[1] = t->b; m[5] = t->d; m[13] = t->ty;
40}
41
42void GLToCGAffine(const GLfloat *m, CGAffineTransform *t)
43{
44 t->a = m[0]; t->c = m[4]; t->tx = m[12];
45 t->b = m[1]; t->d = m[5]; t->ty = m[13];
46}
diff --git a/libs/cocos2d/Support/ZipUtils.h b/libs/cocos2d/Support/ZipUtils.h new file mode 100755 index 0000000..363f911 --- /dev/null +++ b/libs/cocos2d/Support/ZipUtils.h
@@ -0,0 +1,91 @@
1/* cocos2d for iPhone
2 *
3 * http://www.cocos2d-iphone.org
4 *
5 *
6 * inflateMemory_ based on zlib example code
7 * http://www.zlib.net
8 *
9 * Some ideas were taken from:
10 * http://themanaworld.org/
11 * from the mapreader.cpp file
12 *
13 */
14
15#ifndef __CC_ZIP_UTILS_H
16#define __CC_ZIP_UTILS_H
17
18#import <stdint.h>
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24 /* XXX: pragma pack ??? */
25 /** @struct CCZHeader
26 */
27 struct CCZHeader {
28 uint8_t sig[4]; // signature. Should be 'CCZ!' 4 bytes
29 uint16_t compression_type; // should 0
30 uint16_t version; // should be 2 (although version type==1 is also supported)
31 uint32_t reserved; // Reserverd for users.
32 uint32_t len; // size of the uncompressed file
33 };
34
35 enum {
36 CCZ_COMPRESSION_ZLIB, // zlib format.
37 CCZ_COMPRESSION_BZIP2, // bzip2 format (not supported yet)
38 CCZ_COMPRESSION_GZIP, // gzip format (not supported yet)
39 CCZ_COMPRESSION_NONE, // plain (not supported yet)
40 };
41
42/** @file
43 * Zip helper functions
44 */
45
46/**
47 * Inflates either zlib or gzip deflated memory. The inflated memory is
48 * expected to be freed by the caller.
49 *
50 * It will allocate 256k for the destination buffer. If it is not enought it will multiply the previous buffer size per 2, until there is enough memory.
51 * @returns the length of the deflated buffer
52 *
53 @since v0.8.1
54 */
55int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out);
56
57/**
58 * Inflates either zlib or gzip deflated memory. The inflated memory is
59 * expected to be freed by the caller.
60 *
61 * outLenghtHint is assumed to be the needed room to allocate the inflated buffer.
62 *
63 * @returns the length of the deflated buffer
64 *
65 @since v1.0.0
66 */
67int ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int outLenghtHint );
68
69
70/** inflates a GZip file into memory
71 *
72 * @returns the length of the deflated buffer
73 *
74 * @since v0.99.5
75 */
76int ccInflateGZipFile(const char *filename, unsigned char **out);
77
78/** inflates a CCZ file into memory
79 *
80 * @returns the length of the deflated buffer
81 *
82 * @since v0.99.5
83 */
84int ccInflateCCZFile(const char *filename, unsigned char **out);
85
86
87#ifdef __cplusplus
88}
89#endif
90
91#endif // __CC_ZIP_UTILS_H
diff --git a/libs/cocos2d/Support/ZipUtils.m b/libs/cocos2d/Support/ZipUtils.m new file mode 100755 index 0000000..ccd8bbc --- /dev/null +++ b/libs/cocos2d/Support/ZipUtils.m
@@ -0,0 +1,251 @@
1/* cocos2d for iPhone
2 *
3 * http://www.cocos2d-iphone.org
4 *
5 *
6 * Inflates either zlib or gzip deflated memory. The inflated memory is
7 * expected to be freed by the caller.
8 *
9 * inflateMemory_ based on zlib example code
10 * http://www.zlib.net
11 *
12 * Some ideas were taken from:
13 * http://themanaworld.org/
14 * from the mapreader.cpp file
15 */
16
17#import <Availability.h>
18
19#import <zlib.h>
20#import <stdlib.h>
21#import <assert.h>
22#import <stdio.h>
23
24#import "ZipUtils.h"
25#import "CCFileUtils.h"
26#import "../ccMacros.h"
27
28// memory in iPhone is precious
29// Should buffer factor be 1.5 instead of 2 ?
30#define BUFFER_INC_FACTOR (2)
31
32static int inflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int *outLength, unsigned int outLenghtHint )
33{
34 /* ret value */
35 int err = Z_OK;
36
37 int bufferSize = outLenghtHint;
38 *out = (unsigned char*) malloc(bufferSize);
39
40 z_stream d_stream; /* decompression stream */
41 d_stream.zalloc = (alloc_func)0;
42 d_stream.zfree = (free_func)0;
43 d_stream.opaque = (voidpf)0;
44
45 d_stream.next_in = in;
46 d_stream.avail_in = inLength;
47 d_stream.next_out = *out;
48 d_stream.avail_out = bufferSize;
49
50 /* window size to hold 256k */
51 if( (err = inflateInit2(&d_stream, 15 + 32)) != Z_OK )
52 return err;
53
54 for (;;) {
55 err = inflate(&d_stream, Z_NO_FLUSH);
56
57 if (err == Z_STREAM_END)
58 break;
59
60 switch (err) {
61 case Z_NEED_DICT:
62 err = Z_DATA_ERROR;
63 case Z_DATA_ERROR:
64 case Z_MEM_ERROR:
65 inflateEnd(&d_stream);
66 return err;
67 }
68
69 // not enough memory ?
70 if (err != Z_STREAM_END) {
71
72 unsigned char *tmp = realloc(*out, bufferSize * BUFFER_INC_FACTOR);
73
74 /* not enough memory, ouch */
75 if (! tmp ) {
76 CCLOG(@"cocos2d: ZipUtils: realloc failed");
77 inflateEnd(&d_stream);
78 return Z_MEM_ERROR;
79 }
80 /* only assign to *out if tmp is valid. it's not guaranteed that realloc will reuse the memory */
81 *out = tmp;
82
83 d_stream.next_out = *out + bufferSize;
84 d_stream.avail_out = bufferSize;
85 bufferSize *= BUFFER_INC_FACTOR;
86 }
87 }
88
89
90 *outLength = bufferSize - d_stream.avail_out;
91 err = inflateEnd(&d_stream);
92 return err;
93}
94
95int ccInflateMemoryWithHint(unsigned char *in, unsigned int inLength, unsigned char **out, unsigned int outLengthHint )
96{
97 unsigned int outLength = 0;
98 int err = inflateMemoryWithHint(in, inLength, out, &outLength, outLengthHint );
99
100 if (err != Z_OK || *out == NULL) {
101 if (err == Z_MEM_ERROR)
102 CCLOG(@"cocos2d: ZipUtils: Out of memory while decompressing map data!");
103
104 else if (err == Z_VERSION_ERROR)
105 CCLOG(@"cocos2d: ZipUtils: Incompatible zlib version!");
106
107 else if (err == Z_DATA_ERROR)
108 CCLOG(@"cocos2d: ZipUtils: Incorrect zlib compressed data!");
109
110 else
111 CCLOG(@"cocos2d: ZipUtils: Unknown error while decompressing map data!");
112
113 free(*out);
114 *out = NULL;
115 outLength = 0;
116 }
117
118 return outLength;
119}
120
121int ccInflateMemory(unsigned char *in, unsigned int inLength, unsigned char **out)
122{
123 // 256k for hint
124 return ccInflateMemoryWithHint(in, inLength, out, 256 * 1024 );
125}
126
127int ccInflateGZipFile(const char *path, unsigned char **out)
128{
129 int len;
130 unsigned int offset = 0;
131
132 NSCAssert( out, @"ccInflateGZipFile: invalid 'out' parameter");
133 NSCAssert( &*out, @"ccInflateGZipFile: invalid 'out' parameter");
134
135 gzFile inFile = gzopen(path, "rb");
136 if( inFile == NULL ) {
137 CCLOG(@"cocos2d: ZipUtils: error open gzip file: %s", path);
138 return -1;
139 }
140
141 /* 512k initial decompress buffer */
142 int bufferSize = 512 * 1024;
143 unsigned int totalBufferSize = bufferSize;
144
145 *out = malloc( bufferSize );
146 if( ! out ) {
147 CCLOG(@"cocos2d: ZipUtils: out of memory");
148 return -1;
149 }
150
151 for (;;) {
152 len = gzread(inFile, *out + offset, bufferSize);
153 if (len < 0) {
154 CCLOG(@"cocos2d: ZipUtils: error in gzread");
155 free( *out );
156 *out = NULL;
157 return -1;
158 }
159 if (len == 0)
160 break;
161
162 offset += len;
163
164 // finish reading the file
165 if( len < bufferSize )
166 break;
167
168 bufferSize *= BUFFER_INC_FACTOR;
169 totalBufferSize += bufferSize;
170 unsigned char *tmp = realloc(*out, totalBufferSize );
171
172 if( ! tmp ) {
173 CCLOG(@"cocos2d: ZipUtils: out of memory");
174 free( *out );
175 *out = NULL;
176 return -1;
177 }
178
179 *out = tmp;
180 }
181
182 if (gzclose(inFile) != Z_OK)
183 CCLOG(@"cocos2d: ZipUtils: gzclose failed");
184
185 return offset;
186}
187
188int ccInflateCCZFile(const char *path, unsigned char **out)
189{
190 NSCAssert( out, @"ccInflateCCZFile: invalid 'out' parameter");
191 NSCAssert( &*out, @"ccInflateCCZFile: invalid 'out' parameter");
192
193 // load file into memory
194 unsigned char *compressed = NULL;
195 NSInteger fileLen = ccLoadFileIntoMemory( path, &compressed );
196 if( fileLen < 0 ) {
197 CCLOG(@"cocos2d: Error loading CCZ compressed file");
198 }
199
200 struct CCZHeader *header = (struct CCZHeader*) compressed;
201
202 // verify header
203 if( header->sig[0] != 'C' || header->sig[1] != 'C' || header->sig[2] != 'Z' || header->sig[3] != '!' ) {
204 CCLOG(@"cocos2d: Invalid CCZ file");
205 free(compressed);
206 return -1;
207 }
208
209 // verify header version
210 uint16_t version = CFSwapInt16BigToHost( header->version );
211 if( version > 2 ) {
212 CCLOG(@"cocos2d: Unsupported CCZ header format");
213 free(compressed);
214 return -1;
215 }
216
217 // verify compression format
218 if( CFSwapInt16BigToHost(header->compression_type) != CCZ_COMPRESSION_ZLIB ) {
219 CCLOG(@"cocos2d: CCZ Unsupported compression method");
220 free(compressed);
221 return -1;
222 }
223
224 uint32_t len = CFSwapInt32BigToHost( header->len );
225
226 *out = malloc( len );
227 if(! *out )
228 {
229 CCLOG(@"cocos2d: CCZ: Failed to allocate memory for texture");
230 free(compressed);
231 return -1;
232 }
233
234
235 uLongf destlen = len;
236 uLongf source = (uLongf) compressed + sizeof(*header);
237 int ret = uncompress(*out, &destlen, (Bytef*)source, fileLen - sizeof(*header) );
238
239 free( compressed );
240
241 if( ret != Z_OK )
242 {
243 CCLOG(@"cocos2d: CCZ: Failed to uncompress data");
244 free( *out );
245 *out = NULL;
246 return -1;
247 }
248
249
250 return len;
251}
diff --git a/libs/cocos2d/Support/base64.c b/libs/cocos2d/Support/base64.c new file mode 100755 index 0000000..9aa52a6 --- /dev/null +++ b/libs/cocos2d/Support/base64.c
@@ -0,0 +1,93 @@
1/*
2 public domain BASE64 code
3
4 modified for cocos2d-iphone: http://www.cocos2d-iphone.org
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9
10#include "base64.h"
11
12unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13
14int _base64Decode( unsigned char *input, unsigned int input_len, unsigned char *output, unsigned int *output_len );
15
16int _base64Decode( unsigned char *input, unsigned int input_len, unsigned char *output, unsigned int *output_len )
17{
18 static char inalphabet[256], decoder[256];
19 int i, bits, c, char_count, errors = 0;
20 unsigned int input_idx = 0;
21 unsigned int output_idx = 0;
22
23 for (i = (sizeof alphabet) - 1; i >= 0 ; i--) {
24 inalphabet[alphabet[i]] = 1;
25 decoder[alphabet[i]] = i;
26 }
27
28 char_count = 0;
29 bits = 0;
30 for( input_idx=0; input_idx < input_len ; input_idx++ ) {
31 c = input[ input_idx ];
32 if (c == '=')
33 break;
34 if (c > 255 || ! inalphabet[c])
35 continue;
36 bits += decoder[c];
37 char_count++;
38 if (char_count == 4) {
39 output[ output_idx++ ] = (bits >> 16);
40 output[ output_idx++ ] = ((bits >> 8) & 0xff);
41 output[ output_idx++ ] = ( bits & 0xff);
42 bits = 0;
43 char_count = 0;
44 } else {
45 bits <<= 6;
46 }
47 }
48
49 if( c == '=' ) {
50 switch (char_count) {
51 case 1:
52 fprintf(stderr, "base64Decode: encoding incomplete: at least 2 bits missing");
53 errors++;
54 break;
55 case 2:
56 output[ output_idx++ ] = ( bits >> 10 );
57 break;
58 case 3:
59 output[ output_idx++ ] = ( bits >> 16 );
60 output[ output_idx++ ] = (( bits >> 8 ) & 0xff);
61 break;
62 }
63 } else if ( input_idx < input_len ) {
64 if (char_count) {
65 fprintf(stderr, "base64 encoding incomplete: at least %d bits truncated",
66 ((4 - char_count) * 6));
67 errors++;
68 }
69 }
70
71 *output_len = output_idx;
72 return errors;
73}
74
75int base64Decode(unsigned char *in, unsigned int inLength, unsigned char **out)
76{
77 unsigned int outLength = 0;
78
79 //should be enough to store 6-bit buffers in 8-bit buffers
80 *out = malloc( inLength * 3.0f / 4.0f + 1 );
81 if( *out ) {
82 int ret = _base64Decode(in, inLength, *out, &outLength);
83
84 if (ret > 0 )
85 {
86 printf("Base64Utils: error decoding");
87 free(*out);
88 *out = NULL;
89 outLength = 0;
90 }
91 }
92 return outLength;
93}
diff --git a/libs/cocos2d/Support/base64.h b/libs/cocos2d/Support/base64.h new file mode 100755 index 0000000..d30878e --- /dev/null +++ b/libs/cocos2d/Support/base64.h
@@ -0,0 +1,33 @@
1/*
2 public domain BASE64 code
3
4 modified for cocos2d-iphone: http://www.cocos2d-iphone.org
5 */
6
7#ifndef __CC_BASE64_DECODE_H
8#define __CC_BASE64_DECODE_H
9
10#ifdef __cplusplus
11extern "C" {
12#endif
13
14
15/** @file
16 base64 helper functions
17 */
18
19/**
20 * Decodes a 64base encoded memory. The decoded memory is
21 * expected to be freed by the caller.
22 *
23 * @returns the length of the out buffer
24 *
25 @since v0.8.1
26 */
27int base64Decode(unsigned char *in, unsigned int inLength, unsigned char **out);
28
29#ifdef __cplusplus
30}
31#endif
32
33#endif // __CC_BASE64_DECODE_H
diff --git a/libs/cocos2d/Support/ccCArray.h b/libs/cocos2d/Support/ccCArray.h new file mode 100755 index 0000000..20d9633 --- /dev/null +++ b/libs/cocos2d/Support/ccCArray.h
@@ -0,0 +1,447 @@
1/* Copyright (c) 2007 Scott Lembcke
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 * SOFTWARE.
20 */
21
22/**
23 @file
24 Based on Chipmunk cpArray.
25 ccArray is a faster alternative to NSMutableArray, it does pretty much the
26 same thing (stores NSObjects and retains/releases them appropriately). It's
27 faster because:
28 - it uses a plain C interface so it doesn't incur Objective-c messaging overhead
29 - it assumes you know what you're doing, so it doesn't spend time on safety checks
30 (index out of bounds, required capacity etc.)
31 - comparisons are done using pointer equality instead of isEqual
32
33 There are 2 kind of functions:
34 - ccArray functions that manipulates objective-c objects (retain and release are performanced)
35 - ccCArray functions that manipulates values like if they were standard C structures (no retain/release is performed)
36 */
37
38#ifndef CC_ARRAY_H
39#define CC_ARRAY_H
40
41#import <Foundation/Foundation.h>
42
43#import <stdlib.h>
44#import <string.h>
45
46
47#pragma mark -
48#pragma mark ccArray for Objects
49
50// Easy integration
51#define CCARRAYDATA_FOREACH(__array__, __object__) \
52__object__=__array__->arr[0]; for(NSUInteger i=0, num=__array__->num; i<num; i++, __object__=__array__->arr[i]) \
53
54
55typedef struct ccArray {
56 NSUInteger num, max;
57 id *arr;
58} ccArray;
59
60/** Allocates and initializes a new array with specified capacity */
61static inline ccArray* ccArrayNew(NSUInteger capacity) {
62 if (capacity == 0)
63 capacity = 1;
64
65 ccArray *arr = (ccArray*)malloc( sizeof(ccArray) );
66 arr->num = 0;
67 arr->arr = (id*) malloc( capacity * sizeof(id) );
68 arr->max = capacity;
69
70 return arr;
71}
72
73static inline void ccArrayRemoveAllObjects(ccArray *arr);
74
75/** Frees array after removing all remaining objects. Silently ignores nil arr. */
76static inline void ccArrayFree(ccArray *arr)
77{
78 if( arr == nil ) return;
79
80 ccArrayRemoveAllObjects(arr);
81
82 free(arr->arr);
83 free(arr);
84}
85
86/** Doubles array capacity */
87static inline void ccArrayDoubleCapacity(ccArray *arr)
88{
89 arr->max *= 2;
90 id *newArr = (id *)realloc( arr->arr, arr->max * sizeof(id) );
91 // will fail when there's not enough memory
92 NSCAssert(newArr != NULL, @"ccArrayDoubleCapacity failed. Not enough memory");
93 arr->arr = newArr;
94}
95
96/** Increases array capacity such that max >= num + extra. */
97static inline void ccArrayEnsureExtraCapacity(ccArray *arr, NSUInteger extra)
98{
99 while (arr->max < arr->num + extra)
100 ccArrayDoubleCapacity(arr);
101}
102
103/** shrinks the array so the memory footprint corresponds with the number of items */
104static inline void ccArrayShrink(ccArray *arr)
105{
106 NSUInteger newSize;
107
108 //only resize when necessary
109 if (arr->max > arr->num && !(arr->num==0 && arr->max==1))
110 {
111 if (arr->num!=0)
112 {
113 newSize=arr->num;
114 arr->max=arr->num;
115 }
116 else
117 {//minimum capacity of 1, with 0 elements the array would be free'd by realloc
118 newSize=1;
119 arr->max=1;
120 }
121
122 arr->arr = (id*) realloc(arr->arr,newSize * sizeof(id) );
123 NSCAssert(arr->arr!=NULL,@"could not reallocate the memory");
124 }
125}
126
127/** Returns index of first occurence of object, NSNotFound if object not found. */
128static inline NSUInteger ccArrayGetIndexOfObject(ccArray *arr, id object)
129{
130 for( NSUInteger i = 0; i < arr->num; i++)
131 if( arr->arr[i] == object ) return i;
132
133 return NSNotFound;
134}
135
136/** Returns a Boolean value that indicates whether object is present in array. */
137static inline BOOL ccArrayContainsObject(ccArray *arr, id object)
138{
139 return ccArrayGetIndexOfObject(arr, object) != NSNotFound;
140}
141
142/** Appends an object. Bahaviour undefined if array doesn't have enough capacity. */
143static inline void ccArrayAppendObject(ccArray *arr, id object)
144{
145 arr->arr[arr->num] = [object retain];
146 arr->num++;
147}
148
149/** Appends an object. Capacity of arr is increased if needed. */
150static inline void ccArrayAppendObjectWithResize(ccArray *arr, id object)
151{
152 ccArrayEnsureExtraCapacity(arr, 1);
153 ccArrayAppendObject(arr, object);
154}
155
156/** Appends objects from plusArr to arr. Behaviour undefined if arr doesn't have
157 enough capacity. */
158static inline void ccArrayAppendArray(ccArray *arr, ccArray *plusArr)
159{
160 for( NSUInteger i = 0; i < plusArr->num; i++)
161 ccArrayAppendObject(arr, plusArr->arr[i]);
162}
163
164/** Appends objects from plusArr to arr. Capacity of arr is increased if needed. */
165static inline void ccArrayAppendArrayWithResize(ccArray *arr, ccArray *plusArr)
166{
167 ccArrayEnsureExtraCapacity(arr, plusArr->num);
168 ccArrayAppendArray(arr, plusArr);
169}
170
171/** Inserts an object at index */
172static inline void ccArrayInsertObjectAtIndex(ccArray *arr, id object, NSUInteger index)
173{
174 NSCAssert(index<=arr->num, @"Invalid index. Out of bounds");
175
176 ccArrayEnsureExtraCapacity(arr, 1);
177
178 NSUInteger remaining = arr->num - index;
179 if( remaining > 0)
180 memmove(&arr->arr[index+1], &arr->arr[index], sizeof(id) * remaining );
181
182 arr->arr[index] = [object retain];
183 arr->num++;
184}
185
186/** Swaps two objects */
187static inline void ccArraySwapObjectsAtIndexes(ccArray *arr, NSUInteger index1, NSUInteger index2)
188{
189 NSCAssert(index1 < arr->num, @"(1) Invalid index. Out of bounds");
190 NSCAssert(index2 < arr->num, @"(2) Invalid index. Out of bounds");
191
192 id object1 = arr->arr[index1];
193
194 arr->arr[index1] = arr->arr[index2];
195 arr->arr[index2] = object1;
196}
197
198/** Removes all objects from arr */
199static inline void ccArrayRemoveAllObjects(ccArray *arr)
200{
201 while( arr->num > 0 )
202 [arr->arr[--arr->num] release];
203}
204
205/** Removes object at specified index and pushes back all subsequent objects.
206 Behaviour undefined if index outside [0, num-1]. */
207static inline void ccArrayRemoveObjectAtIndex(ccArray *arr, NSUInteger index)
208{
209 [arr->arr[index] release];
210 arr->num--;
211
212 NSUInteger remaining = arr->num - index;
213 if(remaining>0)
214 memmove(&arr->arr[index], &arr->arr[index+1], remaining * sizeof(id));
215}
216
217/** Removes object at specified index and fills the gap with the last object,
218 thereby avoiding the need to push back subsequent objects.
219 Behaviour undefined if index outside [0, num-1]. */
220static inline void ccArrayFastRemoveObjectAtIndex(ccArray *arr, NSUInteger index)
221{
222 [arr->arr[index] release];
223 NSUInteger last = --arr->num;
224 arr->arr[index] = arr->arr[last];
225}
226
227static inline void ccArrayFastRemoveObject(ccArray *arr, id object)
228{
229 NSUInteger index = ccArrayGetIndexOfObject(arr, object);
230 if (index != NSNotFound)
231 ccArrayFastRemoveObjectAtIndex(arr, index);
232}
233
234/** Searches for the first occurance of object and removes it. If object is not
235 found the function has no effect. */
236static inline void ccArrayRemoveObject(ccArray *arr, id object)
237{
238 NSUInteger index = ccArrayGetIndexOfObject(arr, object);
239 if (index != NSNotFound)
240 ccArrayRemoveObjectAtIndex(arr, index);
241}
242
243/** Removes from arr all objects in minusArr. For each object in minusArr, the
244 first matching instance in arr will be removed. */
245static inline void ccArrayRemoveArray(ccArray *arr, ccArray *minusArr)
246{
247 for( NSUInteger i = 0; i < minusArr->num; i++)
248 ccArrayRemoveObject(arr, minusArr->arr[i]);
249}
250
251/** Removes from arr all objects in minusArr. For each object in minusArr, all
252 matching instances in arr will be removed. */
253static inline void ccArrayFullRemoveArray(ccArray *arr, ccArray *minusArr)
254{
255 NSUInteger back = 0;
256
257 for( NSUInteger i = 0; i < arr->num; i++) {
258 if( ccArrayContainsObject(minusArr, arr->arr[i]) ) {
259 [arr->arr[i] release];
260 back++;
261 } else
262 arr->arr[i - back] = arr->arr[i];
263 }
264
265 arr->num -= back;
266}
267
268/** Sends to each object in arr the message identified by given selector. */
269static inline void ccArrayMakeObjectsPerformSelector(ccArray *arr, SEL sel)
270{
271 for( NSUInteger i = 0; i < arr->num; i++)
272 [arr->arr[i] performSelector:sel];
273}
274
275static inline void ccArrayMakeObjectsPerformSelectorWithObject(ccArray *arr, SEL sel, id object)
276{
277 for( NSUInteger i = 0; i < arr->num; i++)
278 [arr->arr[i] performSelector:sel withObject:object];
279}
280
281
282#pragma mark -
283#pragma mark ccCArray for Values (c structures)
284
285typedef ccArray ccCArray;
286
287static inline void ccCArrayRemoveAllValues(ccCArray *arr);
288
289/** Allocates and initializes a new C array with specified capacity */
290static inline ccCArray* ccCArrayNew(NSUInteger capacity) {
291 if (capacity == 0)
292 capacity = 1;
293
294 ccCArray *arr = (ccCArray*)malloc( sizeof(ccCArray) );
295 arr->num = 0;
296 arr->arr = (id*) malloc( capacity * sizeof(id) );
297 arr->max = capacity;
298
299 return arr;
300}
301
302/** Frees C array after removing all remaining values. Silently ignores nil arr. */
303static inline void ccCArrayFree(ccCArray *arr)
304{
305 if( arr == nil ) return;
306
307 ccCArrayRemoveAllValues(arr);
308
309 free(arr->arr);
310 free(arr);
311}
312
313/** Doubles C array capacity */
314static inline void ccCArrayDoubleCapacity(ccCArray *arr)
315{
316 ccArrayDoubleCapacity(arr);
317}
318
319/** Increases array capacity such that max >= num + extra. */
320static inline void ccCArrayEnsureExtraCapacity(ccCArray *arr, NSUInteger extra)
321{
322 ccArrayEnsureExtraCapacity(arr,extra);
323}
324
325/** Returns index of first occurence of value, NSNotFound if value not found. */
326static inline NSUInteger ccCArrayGetIndexOfValue(ccCArray *arr, void* value)
327{
328 for( NSUInteger i = 0; i < arr->num; i++)
329 if( arr->arr[i] == value ) return i;
330 return NSNotFound;
331}
332
333/** Returns a Boolean value that indicates whether value is present in the C array. */
334static inline BOOL ccCArrayContainsValue(ccCArray *arr, void* value)
335{
336 return ccCArrayGetIndexOfValue(arr, value) != NSNotFound;
337}
338
339/** Inserts a value at a certain position. Behaviour undefined if aray doesn't have enough capacity */
340static inline void ccCArrayInsertValueAtIndex( ccCArray *arr, void *value, NSUInteger index)
341{
342 NSCAssert( index < arr->max, @"ccCArrayInsertValueAtIndex: invalid index");
343
344 NSUInteger remaining = arr->num - index;
345
346 // last Value doesn't need to be moved
347 if( remaining > 0) {
348 // tex coordinates
349 memmove( &arr->arr[index+1],&arr->arr[index], sizeof(void*) * remaining );
350 }
351
352 arr->num++;
353 arr->arr[index] = (id) value;
354}
355
356/** Appends an value. Bahaviour undefined if array doesn't have enough capacity. */
357static inline void ccCArrayAppendValue(ccCArray *arr, void* value)
358{
359 arr->arr[arr->num] = (id) value;
360 arr->num++;
361}
362
363/** Appends an value. Capacity of arr is increased if needed. */
364static inline void ccCArrayAppendValueWithResize(ccCArray *arr, void* value)
365{
366 ccCArrayEnsureExtraCapacity(arr, 1);
367 ccCArrayAppendValue(arr, value);
368}
369
370/** Appends values from plusArr to arr. Behaviour undefined if arr doesn't have
371 enough capacity. */
372static inline void ccCArrayAppendArray(ccCArray *arr, ccCArray *plusArr)
373{
374 for( NSUInteger i = 0; i < plusArr->num; i++)
375 ccCArrayAppendValue(arr, plusArr->arr[i]);
376}
377
378/** Appends values from plusArr to arr. Capacity of arr is increased if needed. */
379static inline void ccCArrayAppendArrayWithResize(ccCArray *arr, ccCArray *plusArr)
380{
381 ccCArrayEnsureExtraCapacity(arr, plusArr->num);
382 ccCArrayAppendArray(arr, plusArr);
383}
384
385/** Removes all values from arr */
386static inline void ccCArrayRemoveAllValues(ccCArray *arr)
387{
388 arr->num = 0;
389}
390
391/** Removes value at specified index and pushes back all subsequent values.
392 Behaviour undefined if index outside [0, num-1].
393 @since v0.99.4
394 */
395static inline void ccCArrayRemoveValueAtIndex(ccCArray *arr, NSUInteger index)
396{
397 for( NSUInteger last = --arr->num; index < last; index++)
398 arr->arr[index] = arr->arr[index + 1];
399}
400
401/** Removes value at specified index and fills the gap with the last value,
402 thereby avoiding the need to push back subsequent values.
403 Behaviour undefined if index outside [0, num-1].
404 @since v0.99.4
405 */
406static inline void ccCArrayFastRemoveValueAtIndex(ccCArray *arr, NSUInteger index)
407{
408 NSUInteger last = --arr->num;
409 arr->arr[index] = arr->arr[last];
410}
411
412/** Searches for the first occurance of value and removes it. If value is not found the function has no effect.
413 @since v0.99.4
414 */
415static inline void ccCArrayRemoveValue(ccCArray *arr, void* value)
416{
417 NSUInteger index = ccCArrayGetIndexOfValue(arr, value);
418 if (index != NSNotFound)
419 ccCArrayRemoveValueAtIndex(arr, index);
420}
421
422/** Removes from arr all values in minusArr. For each Value in minusArr, the first matching instance in arr will be removed.
423 @since v0.99.4
424 */
425static inline void ccCArrayRemoveArray(ccCArray *arr, ccCArray *minusArr)
426{
427 for( NSUInteger i = 0; i < minusArr->num; i++)
428 ccCArrayRemoveValue(arr, minusArr->arr[i]);
429}
430
431/** Removes from arr all values in minusArr. For each value in minusArr, all matching instances in arr will be removed.
432 @since v0.99.4
433 */
434static inline void ccCArrayFullRemoveArray(ccCArray *arr, ccCArray *minusArr)
435{
436 NSUInteger back = 0;
437
438 for( NSUInteger i = 0; i < arr->num; i++) {
439 if( ccCArrayContainsValue(minusArr, arr->arr[i]) ) {
440 back++;
441 } else
442 arr->arr[i - back] = arr->arr[i];
443 }
444
445 arr->num -= back;
446}
447#endif // CC_ARRAY_H
diff --git a/libs/cocos2d/Support/ccUtils.c b/libs/cocos2d/Support/ccUtils.c new file mode 100755 index 0000000..39786ec --- /dev/null +++ b/libs/cocos2d/Support/ccUtils.c
@@ -0,0 +1,20 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 */
5
6/*
7 ccNextPOT function is licensed under the same license that is used in CCTexture2D.m.
8 */
9#include "ccUtils.h"
10
11unsigned long ccNextPOT(unsigned long x)
12{
13 x = x - 1;
14 x = x | (x >> 1);
15 x = x | (x >> 2);
16 x = x | (x >> 4);
17 x = x | (x >> 8);
18 x = x | (x >>16);
19 return x + 1;
20} \ No newline at end of file
diff --git a/libs/cocos2d/Support/ccUtils.h b/libs/cocos2d/Support/ccUtils.h new file mode 100755 index 0000000..783fc54 --- /dev/null +++ b/libs/cocos2d/Support/ccUtils.h
@@ -0,0 +1,29 @@
1/*
2 * cocos2d for iPhone: http://www.cocos2d-iphone.org
3 *
4 */
5
6#ifndef __CC_UTILS_H
7#define __CC_UTILS_H
8
9/** @file ccUtils.h
10 Misc free functions
11 */
12
13/*
14 ccNextPOT function is licensed under the same license that is used in CCTexture2D.m.
15 */
16
17/** returns the Next Power of Two value.
18
19 Examples:
20 - If "value" is 15, it will return 16.
21 - If "value" is 16, it will return 16.
22 - If "value" is 17, it will return 32.
23
24 @since v0.99.5
25 */
26
27unsigned long ccNextPOT( unsigned long value );
28
29#endif // ! __CC_UTILS_H
diff --git a/libs/cocos2d/Support/uthash.h b/libs/cocos2d/Support/uthash.h new file mode 100755 index 0000000..a4bdc18 --- /dev/null +++ b/libs/cocos2d/Support/uthash.h
@@ -0,0 +1,972 @@
1/*
2Copyright (c) 2003-2010, Troy D. Hanson http://uthash.sourceforge.net
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
12IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
15OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22*/
23
24#ifndef UTHASH_H
25#define UTHASH_H
26
27#include <string.h> /* memcmp,strlen */
28#include <stddef.h> /* ptrdiff_t */
29
30/* These macros use decltype or the earlier __typeof GNU extension.
31 As decltype is only available in newer compilers (VS2010 or gcc 4.3+
32 when compiling c++ source) this code uses whatever method is needed
33 or, for VS2008 where neither is available, uses casting workarounds. */
34#ifdef _MSC_VER /* MS compiler */
35#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
36#define DECLTYPE(x) (decltype(x))
37#else /* VS2008 or older (or VS2010 in C mode) */
38#define NO_DECLTYPE
39#define DECLTYPE(x)
40#endif
41#else /* GNU, Sun and other compilers */
42#define DECLTYPE(x) (__typeof(x))
43#endif
44
45#ifdef NO_DECLTYPE
46#define DECLTYPE_ASSIGN(dst,src) \
47do { \
48 char **_da_dst = (char**)(&(dst)); \
49 *_da_dst = (char*)(src); \
50} while(0)
51#else
52#define DECLTYPE_ASSIGN(dst,src) \
53do { \
54 (dst) = DECLTYPE(dst)(src); \
55} while(0)
56#endif
57
58/* a number of the hash function use uint32_t which isn't defined on win32 */
59#ifdef _MSC_VER
60typedef unsigned int uint32_t;
61#else
62#include <inttypes.h> /* uint32_t */
63#endif
64
65#define UTHASH_VERSION 1.9.3
66
67#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
68#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
69#define uthash_free(ptr,sz) free(ptr) /* free fcn */
70
71#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
72#define uthash_expand_fyi(tbl) /* can be defined to log expands */
73
74/* initial number of buckets */
75#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
76#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
77#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
78
79/* calculate the element whose hash handle address is hhe */
80#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
81
82#define HASH_FIND(hh,head,keyptr,keylen,out) \
83do { \
84 unsigned _hf_bkt,_hf_hashv; \
85 out=NULL; \
86 if (head) { \
87 HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
88 if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
89 HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
90 keyptr,keylen,out); \
91 } \
92 } \
93} while (0)
94
95#ifdef HASH_BLOOM
96#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
97#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
98#define HASH_BLOOM_MAKE(tbl) \
99do { \
100 (tbl)->bloom_nbits = HASH_BLOOM; \
101 (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
102 if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
103 memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
104 (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
105} while (0);
106
107#define HASH_BLOOM_FREE(tbl) \
108do { \
109 uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
110} while (0);
111
112#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
113#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
114
115#define HASH_BLOOM_ADD(tbl,hashv) \
116 HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
117
118#define HASH_BLOOM_TEST(tbl,hashv) \
119 HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
120
121#else
122#define HASH_BLOOM_MAKE(tbl)
123#define HASH_BLOOM_FREE(tbl)
124#define HASH_BLOOM_ADD(tbl,hashv)
125#define HASH_BLOOM_TEST(tbl,hashv) (1)
126#endif
127
128#define HASH_MAKE_TABLE(hh,head) \
129do { \
130 (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
131 sizeof(UT_hash_table)); \
132 if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
133 memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
134 (head)->hh.tbl->tail = &((head)->hh); \
135 (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
136 (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
137 (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
138 (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
139 HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
140 if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
141 memset((head)->hh.tbl->buckets, 0, \
142 HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
143 HASH_BLOOM_MAKE((head)->hh.tbl); \
144 (head)->hh.tbl->signature = HASH_SIGNATURE; \
145} while(0)
146
147#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
148 HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
149
150#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
151do { \
152 unsigned _ha_bkt; \
153 (add)->hh.next = NULL; \
154 (add)->hh.key = (char*)keyptr; \
155 (add)->hh.keylen = keylen_in; \
156 if (!(head)) { \
157 head = (add); \
158 (head)->hh.prev = NULL; \
159 HASH_MAKE_TABLE(hh,head); \
160 } else { \
161 (head)->hh.tbl->tail->next = (add); \
162 (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
163 (head)->hh.tbl->tail = &((add)->hh); \
164 } \
165 (head)->hh.tbl->num_items++; \
166 (add)->hh.tbl = (head)->hh.tbl; \
167 HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
168 (add)->hh.hashv, _ha_bkt); \
169 HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
170 HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
171 HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
172 HASH_FSCK(hh,head); \
173} while(0)
174
175#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
176do { \
177 bkt = ((hashv) & ((num_bkts) - 1)); \
178} while(0)
179
180/* delete "delptr" from the hash table.
181 * "the usual" patch-up process for the app-order doubly-linked-list.
182 * The use of _hd_hh_del below deserves special explanation.
183 * These used to be expressed using (delptr) but that led to a bug
184 * if someone used the same symbol for the head and deletee, like
185 * HASH_DELETE(hh,users,users);
186 * We want that to work, but by changing the head (users) below
187 * we were forfeiting our ability to further refer to the deletee (users)
188 * in the patch-up process. Solution: use scratch space to
189 * copy the deletee pointer, then the latter references are via that
190 * scratch pointer rather than through the repointed (users) symbol.
191 */
192#define HASH_DELETE(hh,head,delptr) \
193do { \
194 unsigned _hd_bkt; \
195 struct UT_hash_handle *_hd_hh_del; \
196 if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
197 uthash_free((head)->hh.tbl->buckets, \
198 (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
199 HASH_BLOOM_FREE((head)->hh.tbl); \
200 uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
201 head = NULL; \
202 } else { \
203 _hd_hh_del = &((delptr)->hh); \
204 if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
205 (head)->hh.tbl->tail = \
206 (UT_hash_handle*)((char*)((delptr)->hh.prev) + \
207 (head)->hh.tbl->hho); \
208 } \
209 if ((delptr)->hh.prev) { \
210 ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \
211 (head)->hh.tbl->hho))->next = (delptr)->hh.next; \
212 } else { \
213 DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
214 } \
215 if (_hd_hh_del->next) { \
216 ((UT_hash_handle*)((char*)_hd_hh_del->next + \
217 (head)->hh.tbl->hho))->prev = \
218 _hd_hh_del->prev; \
219 } \
220 HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
221 HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
222 (head)->hh.tbl->num_items--; \
223 } \
224 HASH_FSCK(hh,head); \
225} while (0)
226
227
228/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
229#define HASH_FIND_STR(head,findstr,out) \
230 HASH_FIND(hh,head,findstr,strlen(findstr),out)
231#define HASH_ADD_STR(head,strfield,add) \
232 HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
233#define HASH_FIND_INT(head,findint,out) \
234 HASH_FIND(hh,head,findint,sizeof(int),out)
235#define HASH_ADD_INT(head,intfield,add) \
236 HASH_ADD(hh,head,intfield,sizeof(int),add)
237#define HASH_FIND_PTR(head,findptr,out) \
238 HASH_FIND(hh,head,findptr,sizeof(void *),out)
239#define HASH_ADD_PTR(head,ptrfield,add) \
240 HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
241#define HASH_DEL(head,delptr) \
242 HASH_DELETE(hh,head,delptr)
243
244/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
245 * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
246 */
247#ifdef HASH_DEBUG
248#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
249#define HASH_FSCK(hh,head) \
250do { \
251 unsigned _bkt_i; \
252 unsigned _count, _bkt_count; \
253 char *_prev; \
254 struct UT_hash_handle *_thh; \
255 if (head) { \
256 _count = 0; \
257 for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
258 _bkt_count = 0; \
259 _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
260 _prev = NULL; \
261 while (_thh) { \
262 if (_prev != (char*)(_thh->hh_prev)) { \
263 HASH_OOPS("invalid hh_prev %p, actual %p\n", \
264 _thh->hh_prev, _prev ); \
265 } \
266 _bkt_count++; \
267 _prev = (char*)(_thh); \
268 _thh = _thh->hh_next; \
269 } \
270 _count += _bkt_count; \
271 if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
272 HASH_OOPS("invalid bucket count %d, actual %d\n", \
273 (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
274 } \
275 } \
276 if (_count != (head)->hh.tbl->num_items) { \
277 HASH_OOPS("invalid hh item count %d, actual %d\n", \
278 (head)->hh.tbl->num_items, _count ); \
279 } \
280 /* traverse hh in app order; check next/prev integrity, count */ \
281 _count = 0; \
282 _prev = NULL; \
283 _thh = &(head)->hh; \
284 while (_thh) { \
285 _count++; \
286 if (_prev !=(char*)(_thh->prev)) { \
287 HASH_OOPS("invalid prev %p, actual %p\n", \
288 _thh->prev, _prev ); \
289 } \
290 _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
291 _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
292 (head)->hh.tbl->hho) : NULL ); \
293 } \
294 if (_count != (head)->hh.tbl->num_items) { \
295 HASH_OOPS("invalid app item count %d, actual %d\n", \
296 (head)->hh.tbl->num_items, _count ); \
297 } \
298 } \
299} while (0)
300#else
301#define HASH_FSCK(hh,head)
302#endif
303
304/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
305 * the descriptor to which this macro is defined for tuning the hash function.
306 * The app can #include <unistd.h> to get the prototype for write(2). */
307#ifdef HASH_EMIT_KEYS
308#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
309do { \
310 unsigned _klen = fieldlen; \
311 write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
312 write(HASH_EMIT_KEYS, keyptr, fieldlen); \
313} while (0)
314#else
315#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
316#endif
317
318/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
319#ifdef HASH_FUNCTION
320#define HASH_FCN HASH_FUNCTION
321#else
322#define HASH_FCN HASH_JEN
323#endif
324
325/* The Bernstein hash function, used in Perl prior to v5.6 */
326#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
327do { \
328 unsigned _hb_keylen=keylen; \
329 char *_hb_key=(char*)(key); \
330 (hashv) = 0; \
331 while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
332 bkt = (hashv) & (num_bkts-1); \
333} while (0)
334
335
336/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
337 * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
338#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
339do { \
340 unsigned _sx_i; \
341 char *_hs_key=(char*)(key); \
342 hashv = 0; \
343 for(_sx_i=0; _sx_i < keylen; _sx_i++) \
344 hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
345 bkt = hashv & (num_bkts-1); \
346} while (0)
347
348#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
349do { \
350 unsigned _fn_i; \
351 char *_hf_key=(char*)(key); \
352 hashv = 2166136261UL; \
353 for(_fn_i=0; _fn_i < keylen; _fn_i++) \
354 hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
355 bkt = hashv & (num_bkts-1); \
356} while(0);
357
358#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
359do { \
360 unsigned _ho_i; \
361 char *_ho_key=(char*)(key); \
362 hashv = 0; \
363 for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
364 hashv += _ho_key[_ho_i]; \
365 hashv += (hashv << 10); \
366 hashv ^= (hashv >> 6); \
367 } \
368 hashv += (hashv << 3); \
369 hashv ^= (hashv >> 11); \
370 hashv += (hashv << 15); \
371 bkt = hashv & (num_bkts-1); \
372} while(0)
373
374#define HASH_JEN_MIX(a,b,c) \
375do { \
376 a -= b; a -= c; a ^= ( c >> 13 ); \
377 b -= c; b -= a; b ^= ( a << 8 ); \
378 c -= a; c -= b; c ^= ( b >> 13 ); \
379 a -= b; a -= c; a ^= ( c >> 12 ); \
380 b -= c; b -= a; b ^= ( a << 16 ); \
381 c -= a; c -= b; c ^= ( b >> 5 ); \
382 a -= b; a -= c; a ^= ( c >> 3 ); \
383 b -= c; b -= a; b ^= ( a << 10 ); \
384 c -= a; c -= b; c ^= ( b >> 15 ); \
385} while (0)
386
387#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
388do { \
389 unsigned _hj_i,_hj_j,_hj_k; \
390 char *_hj_key=(char*)(key); \
391 hashv = 0xfeedbeef; \
392 _hj_i = _hj_j = 0x9e3779b9; \
393 _hj_k = keylen; \
394 while (_hj_k >= 12) { \
395 _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
396 + ( (unsigned)_hj_key[2] << 16 ) \
397 + ( (unsigned)_hj_key[3] << 24 ) ); \
398 _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
399 + ( (unsigned)_hj_key[6] << 16 ) \
400 + ( (unsigned)_hj_key[7] << 24 ) ); \
401 hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
402 + ( (unsigned)_hj_key[10] << 16 ) \
403 + ( (unsigned)_hj_key[11] << 24 ) ); \
404 \
405 HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
406 \
407 _hj_key += 12; \
408 _hj_k -= 12; \
409 } \
410 hashv += keylen; \
411 switch ( _hj_k ) { \
412 case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
413 case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
414 case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
415 case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
416 case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
417 case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
418 case 5: _hj_j += _hj_key[4]; \
419 case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
420 case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
421 case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
422 case 1: _hj_i += _hj_key[0]; \
423 } \
424 HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
425 bkt = hashv & (num_bkts-1); \
426} while(0)
427
428/* The Paul Hsieh hash function */
429#undef get16bits
430#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
431 || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
432#define get16bits(d) (*((const uint16_t *) (d)))
433#endif
434
435#if !defined (get16bits)
436#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
437 +(uint32_t)(((const uint8_t *)(d))[0]) )
438#endif
439#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
440do { \
441 char *_sfh_key=(char*)(key); \
442 uint32_t _sfh_tmp, _sfh_len = keylen; \
443 \
444 int _sfh_rem = _sfh_len & 3; \
445 _sfh_len >>= 2; \
446 hashv = 0xcafebabe; \
447 \
448 /* Main loop */ \
449 for (;_sfh_len > 0; _sfh_len--) { \
450 hashv += get16bits (_sfh_key); \
451 _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \
452 hashv = (hashv << 16) ^ _sfh_tmp; \
453 _sfh_key += 2*sizeof (uint16_t); \
454 hashv += hashv >> 11; \
455 } \
456 \
457 /* Handle end cases */ \
458 switch (_sfh_rem) { \
459 case 3: hashv += get16bits (_sfh_key); \
460 hashv ^= hashv << 16; \
461 hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \
462 hashv += hashv >> 11; \
463 break; \
464 case 2: hashv += get16bits (_sfh_key); \
465 hashv ^= hashv << 11; \
466 hashv += hashv >> 17; \
467 break; \
468 case 1: hashv += *_sfh_key; \
469 hashv ^= hashv << 10; \
470 hashv += hashv >> 1; \
471 } \
472 \
473 /* Force "avalanching" of final 127 bits */ \
474 hashv ^= hashv << 3; \
475 hashv += hashv >> 5; \
476 hashv ^= hashv << 4; \
477 hashv += hashv >> 17; \
478 hashv ^= hashv << 25; \
479 hashv += hashv >> 6; \
480 bkt = hashv & (num_bkts-1); \
481} while(0);
482
483#ifdef HASH_USING_NO_STRICT_ALIASING
484/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads.
485 * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
486 * So MurmurHash comes in two versions, the faster unaligned one and the slower
487 * aligned one. We only use the faster one on CPU's where we know it's safe.
488 *
489 * Note the preprocessor built-in defines can be emitted using:
490 *
491 * gcc -m64 -dM -E - < /dev/null (on gcc)
492 * cc -## a.c (where a.c is a simple test file) (Sun Studio)
493 */
494#if (defined(__i386__) || defined(__x86_64__))
495#define HASH_MUR HASH_MUR_UNALIGNED
496#else
497#define HASH_MUR HASH_MUR_ALIGNED
498#endif
499
500/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */
501#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \
502do { \
503 const unsigned int _mur_m = 0x5bd1e995; \
504 const int _mur_r = 24; \
505 hashv = 0xcafebabe ^ keylen; \
506 char *_mur_key = (char *)(key); \
507 uint32_t _mur_tmp, _mur_len = keylen; \
508 \
509 for (;_mur_len >= 4; _mur_len-=4) { \
510 _mur_tmp = *(uint32_t *)_mur_key; \
511 _mur_tmp *= _mur_m; \
512 _mur_tmp ^= _mur_tmp >> _mur_r; \
513 _mur_tmp *= _mur_m; \
514 hashv *= _mur_m; \
515 hashv ^= _mur_tmp; \
516 _mur_key += 4; \
517 } \
518 \
519 switch(_mur_len) \
520 { \
521 case 3: hashv ^= _mur_key[2] << 16; \
522 case 2: hashv ^= _mur_key[1] << 8; \
523 case 1: hashv ^= _mur_key[0]; \
524 hashv *= _mur_m; \
525 }; \
526 \
527 hashv ^= hashv >> 13; \
528 hashv *= _mur_m; \
529 hashv ^= hashv >> 15; \
530 \
531 bkt = hashv & (num_bkts-1); \
532} while(0)
533
534/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */
535#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \
536do { \
537 const unsigned int _mur_m = 0x5bd1e995; \
538 const int _mur_r = 24; \
539 hashv = 0xcafebabe ^ (keylen); \
540 char *_mur_key = (char *)(key); \
541 uint32_t _mur_len = keylen; \
542 int _mur_align = (int)_mur_key & 3; \
543 \
544 if (_mur_align && (_mur_len >= 4)) { \
545 unsigned _mur_t = 0, _mur_d = 0; \
546 switch(_mur_align) { \
547 case 1: _mur_t |= _mur_key[2] << 16; \
548 case 2: _mur_t |= _mur_key[1] << 8; \
549 case 3: _mur_t |= _mur_key[0]; \
550 } \
551 _mur_t <<= (8 * _mur_align); \
552 _mur_key += 4-_mur_align; \
553 _mur_len -= 4-_mur_align; \
554 int _mur_sl = 8 * (4-_mur_align); \
555 int _mur_sr = 8 * _mur_align; \
556 \
557 for (;_mur_len >= 4; _mur_len-=4) { \
558 _mur_d = *(unsigned *)_mur_key; \
559 _mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
560 unsigned _mur_k = _mur_t; \
561 _mur_k *= _mur_m; \
562 _mur_k ^= _mur_k >> _mur_r; \
563 _mur_k *= _mur_m; \
564 hashv *= _mur_m; \
565 hashv ^= _mur_k; \
566 _mur_t = _mur_d; \
567 _mur_key += 4; \
568 } \
569 _mur_d = 0; \
570 if(_mur_len >= _mur_align) { \
571 switch(_mur_align) { \
572 case 3: _mur_d |= _mur_key[2] << 16; \
573 case 2: _mur_d |= _mur_key[1] << 8; \
574 case 1: _mur_d |= _mur_key[0]; \
575 } \
576 unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
577 _mur_k *= _mur_m; \
578 _mur_k ^= _mur_k >> _mur_r; \
579 _mur_k *= _mur_m; \
580 hashv *= _mur_m; \
581 hashv ^= _mur_k; \
582 _mur_k += _mur_align; \
583 _mur_len -= _mur_align; \
584 \
585 switch(_mur_len) \
586 { \
587 case 3: hashv ^= _mur_key[2] << 16; \
588 case 2: hashv ^= _mur_key[1] << 8; \
589 case 1: hashv ^= _mur_key[0]; \
590 hashv *= _mur_m; \
591 } \
592 } else { \
593 switch(_mur_len) \
594 { \
595 case 3: _mur_d ^= _mur_key[2] << 16; \
596 case 2: _mur_d ^= _mur_key[1] << 8; \
597 case 1: _mur_d ^= _mur_key[0]; \
598 case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
599 hashv *= _mur_m; \
600 } \
601 } \
602 \
603 hashv ^= hashv >> 13; \
604 hashv *= _mur_m; \
605 hashv ^= hashv >> 15; \
606 } else { \
607 for (;_mur_len >= 4; _mur_len-=4) { \
608 unsigned _mur_k = *(unsigned*)_mur_key; \
609 _mur_k *= _mur_m; \
610 _mur_k ^= _mur_k >> _mur_r; \
611 _mur_k *= _mur_m; \
612 hashv *= _mur_m; \
613 hashv ^= _mur_k; \
614 _mur_key += 4; \
615 } \
616 switch(_mur_len) \
617 { \
618 case 3: hashv ^= _mur_key[2] << 16; \
619 case 2: hashv ^= _mur_key[1] << 8; \
620 case 1: hashv ^= _mur_key[0]; \
621 hashv *= _mur_m; \
622 } \
623 \
624 hashv ^= hashv >> 13; \
625 hashv *= _mur_m; \
626 hashv ^= hashv >> 15; \
627 } \
628 bkt = hashv & (num_bkts-1); \
629} while(0)
630#endif /* HASH_USING_NO_STRICT_ALIASING */
631
632/* key comparison function; return 0 if keys equal */
633#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
634
635/* iterate over items in a known bucket to find desired item */
636#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
637do { \
638 if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
639 else out=NULL; \
640 while (out) { \
641 if (out->hh.keylen == keylen_in) { \
642 if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \
643 } \
644 if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
645 else out = NULL; \
646 } \
647} while(0)
648
649/* add an item to a bucket */
650#define HASH_ADD_TO_BKT(head,addhh) \
651do { \
652 head.count++; \
653 (addhh)->hh_next = head.hh_head; \
654 (addhh)->hh_prev = NULL; \
655 if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
656 (head).hh_head=addhh; \
657 if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
658 && (addhh)->tbl->noexpand != 1) { \
659 HASH_EXPAND_BUCKETS((addhh)->tbl); \
660 } \
661} while(0)
662
663/* remove an item from a given bucket */
664#define HASH_DEL_IN_BKT(hh,head,hh_del) \
665 (head).count--; \
666 if ((head).hh_head == hh_del) { \
667 (head).hh_head = hh_del->hh_next; \
668 } \
669 if (hh_del->hh_prev) { \
670 hh_del->hh_prev->hh_next = hh_del->hh_next; \
671 } \
672 if (hh_del->hh_next) { \
673 hh_del->hh_next->hh_prev = hh_del->hh_prev; \
674 }
675
676/* Bucket expansion has the effect of doubling the number of buckets
677 * and redistributing the items into the new buckets. Ideally the
678 * items will distribute more or less evenly into the new buckets
679 * (the extent to which this is true is a measure of the quality of
680 * the hash function as it applies to the key domain).
681 *
682 * With the items distributed into more buckets, the chain length
683 * (item count) in each bucket is reduced. Thus by expanding buckets
684 * the hash keeps a bound on the chain length. This bounded chain
685 * length is the essence of how a hash provides constant time lookup.
686 *
687 * The calculation of tbl->ideal_chain_maxlen below deserves some
688 * explanation. First, keep in mind that we're calculating the ideal
689 * maximum chain length based on the *new* (doubled) bucket count.
690 * In fractions this is just n/b (n=number of items,b=new num buckets).
691 * Since the ideal chain length is an integer, we want to calculate
692 * ceil(n/b). We don't depend on floating point arithmetic in this
693 * hash, so to calculate ceil(n/b) with integers we could write
694 *
695 * ceil(n/b) = (n/b) + ((n%b)?1:0)
696 *
697 * and in fact a previous version of this hash did just that.
698 * But now we have improved things a bit by recognizing that b is
699 * always a power of two. We keep its base 2 log handy (call it lb),
700 * so now we can write this with a bit shift and logical AND:
701 *
702 * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
703 *
704 */
705#define HASH_EXPAND_BUCKETS(tbl) \
706do { \
707 unsigned _he_bkt; \
708 unsigned _he_bkt_i; \
709 struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
710 UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
711 _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
712 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
713 if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
714 memset(_he_new_buckets, 0, \
715 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
716 tbl->ideal_chain_maxlen = \
717 (tbl->num_items >> (tbl->log2_num_buckets+1)) + \
718 ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
719 tbl->nonideal_items = 0; \
720 for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
721 { \
722 _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
723 while (_he_thh) { \
724 _he_hh_nxt = _he_thh->hh_next; \
725 HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
726 _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
727 if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
728 tbl->nonideal_items++; \
729 _he_newbkt->expand_mult = _he_newbkt->count / \
730 tbl->ideal_chain_maxlen; \
731 } \
732 _he_thh->hh_prev = NULL; \
733 _he_thh->hh_next = _he_newbkt->hh_head; \
734 if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
735 _he_thh; \
736 _he_newbkt->hh_head = _he_thh; \
737 _he_thh = _he_hh_nxt; \
738 } \
739 } \
740 uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
741 tbl->num_buckets *= 2; \
742 tbl->log2_num_buckets++; \
743 tbl->buckets = _he_new_buckets; \
744 tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
745 (tbl->ineff_expands+1) : 0; \
746 if (tbl->ineff_expands > 1) { \
747 tbl->noexpand=1; \
748 uthash_noexpand_fyi(tbl); \
749 } \
750 uthash_expand_fyi(tbl); \
751} while(0)
752
753
754/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
755/* Note that HASH_SORT assumes the hash handle name to be hh.
756 * HASH_SRT was added to allow the hash handle name to be passed in. */
757#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
758#define HASH_SRT(hh,head,cmpfcn) \
759do { \
760 unsigned _hs_i; \
761 unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
762 struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
763 if (head) { \
764 _hs_insize = 1; \
765 _hs_looping = 1; \
766 _hs_list = &((head)->hh); \
767 while (_hs_looping) { \
768 _hs_p = _hs_list; \
769 _hs_list = NULL; \
770 _hs_tail = NULL; \
771 _hs_nmerges = 0; \
772 while (_hs_p) { \
773 _hs_nmerges++; \
774 _hs_q = _hs_p; \
775 _hs_psize = 0; \
776 for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
777 _hs_psize++; \
778 _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
779 ((void*)((char*)(_hs_q->next) + \
780 (head)->hh.tbl->hho)) : NULL); \
781 if (! (_hs_q) ) break; \
782 } \
783 _hs_qsize = _hs_insize; \
784 while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
785 if (_hs_psize == 0) { \
786 _hs_e = _hs_q; \
787 _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
788 ((void*)((char*)(_hs_q->next) + \
789 (head)->hh.tbl->hho)) : NULL); \
790 _hs_qsize--; \
791 } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
792 _hs_e = _hs_p; \
793 _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
794 ((void*)((char*)(_hs_p->next) + \
795 (head)->hh.tbl->hho)) : NULL); \
796 _hs_psize--; \
797 } else if (( \
798 cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
799 DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
800 ) <= 0) { \
801 _hs_e = _hs_p; \
802 _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
803 ((void*)((char*)(_hs_p->next) + \
804 (head)->hh.tbl->hho)) : NULL); \
805 _hs_psize--; \
806 } else { \
807 _hs_e = _hs_q; \
808 _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
809 ((void*)((char*)(_hs_q->next) + \
810 (head)->hh.tbl->hho)) : NULL); \
811 _hs_qsize--; \
812 } \
813 if ( _hs_tail ) { \
814 _hs_tail->next = ((_hs_e) ? \
815 ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
816 } else { \
817 _hs_list = _hs_e; \
818 } \
819 _hs_e->prev = ((_hs_tail) ? \
820 ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
821 _hs_tail = _hs_e; \
822 } \
823 _hs_p = _hs_q; \
824 } \
825 _hs_tail->next = NULL; \
826 if ( _hs_nmerges <= 1 ) { \
827 _hs_looping=0; \
828 (head)->hh.tbl->tail = _hs_tail; \
829 DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
830 } \
831 _hs_insize *= 2; \
832 } \
833 HASH_FSCK(hh,head); \
834 } \
835} while (0)
836
837/* This function selects items from one hash into another hash.
838 * The end result is that the selected items have dual presence
839 * in both hashes. There is no copy of the items made; rather
840 * they are added into the new hash through a secondary hash
841 * hash handle that must be present in the structure. */
842#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
843do { \
844 unsigned _src_bkt, _dst_bkt; \
845 void *_last_elt=NULL, *_elt; \
846 UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
847 ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
848 if (src) { \
849 for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
850 for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
851 _src_hh; \
852 _src_hh = _src_hh->hh_next) { \
853 _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
854 if (cond(_elt)) { \
855 _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
856 _dst_hh->key = _src_hh->key; \
857 _dst_hh->keylen = _src_hh->keylen; \
858 _dst_hh->hashv = _src_hh->hashv; \
859 _dst_hh->prev = _last_elt; \
860 _dst_hh->next = NULL; \
861 if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
862 if (!dst) { \
863 DECLTYPE_ASSIGN(dst,_elt); \
864 HASH_MAKE_TABLE(hh_dst,dst); \
865 } else { \
866 _dst_hh->tbl = (dst)->hh_dst.tbl; \
867 } \
868 HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
869 HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
870 (dst)->hh_dst.tbl->num_items++; \
871 _last_elt = _elt; \
872 _last_elt_hh = _dst_hh; \
873 } \
874 } \
875 } \
876 } \
877 HASH_FSCK(hh_dst,dst); \
878} while (0)
879
880#define HASH_CLEAR(hh,head) \
881do { \
882 if (head) { \
883 uthash_free((head)->hh.tbl->buckets, \
884 (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
885 uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
886 (head)=NULL; \
887 } \
888} while(0)
889
890#ifdef NO_DECLTYPE
891#define HASH_ITER(hh,head,el,tmp) \
892for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
893 el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
894#else
895#define HASH_ITER(hh,head,el,tmp) \
896for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
897 el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
898#endif
899
900/* obtain a count of items in the hash */
901#define HASH_COUNT(head) HASH_CNT(hh,head)
902#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
903
904typedef struct UT_hash_bucket {
905 struct UT_hash_handle *hh_head;
906 unsigned count;
907
908 /* expand_mult is normally set to 0. In this situation, the max chain length
909 * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
910 * the bucket's chain exceeds this length, bucket expansion is triggered).
911 * However, setting expand_mult to a non-zero value delays bucket expansion
912 * (that would be triggered by additions to this particular bucket)
913 * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
914 * (The multiplier is simply expand_mult+1). The whole idea of this
915 * multiplier is to reduce bucket expansions, since they are expensive, in
916 * situations where we know that a particular bucket tends to be overused.
917 * It is better to let its chain length grow to a longer yet-still-bounded
918 * value, than to do an O(n) bucket expansion too often.
919 */
920 unsigned expand_mult;
921
922} UT_hash_bucket;
923
924/* random signature used only to find hash tables in external analysis */
925#define HASH_SIGNATURE 0xa0111fe1
926#define HASH_BLOOM_SIGNATURE 0xb12220f2
927
928typedef struct UT_hash_table {
929 UT_hash_bucket *buckets;
930 unsigned num_buckets, log2_num_buckets;
931 unsigned num_items;
932 struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
933 ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
934
935 /* in an ideal situation (all buckets used equally), no bucket would have
936 * more than ceil(#items/#buckets) items. that's the ideal chain length. */
937 unsigned ideal_chain_maxlen;
938
939 /* nonideal_items is the number of items in the hash whose chain position
940 * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
941 * hash distribution; reaching them in a chain traversal takes >ideal steps */
942 unsigned nonideal_items;
943
944 /* ineffective expands occur when a bucket doubling was performed, but
945 * afterward, more than half the items in the hash had nonideal chain
946 * positions. If this happens on two consecutive expansions we inhibit any
947 * further expansion, as it's not helping; this happens when the hash
948 * function isn't a good fit for the key domain. When expansion is inhibited
949 * the hash will still work, albeit no longer in constant time. */
950 unsigned ineff_expands, noexpand;
951
952 uint32_t signature; /* used only to find hash tables in external analysis */
953#ifdef HASH_BLOOM
954 uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
955 uint8_t *bloom_bv;
956 char bloom_nbits;
957#endif
958
959} UT_hash_table;
960
961typedef struct UT_hash_handle {
962 struct UT_hash_table *tbl;
963 void *prev; /* prev element in app order */
964 void *next; /* next element in app order */
965 struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
966 struct UT_hash_handle *hh_next; /* next hh in bucket order */
967 void *key; /* ptr to enclosing struct's key */
968 unsigned keylen; /* enclosing struct's key len */
969 unsigned hashv; /* result of hash-fcn(key) */
970} UT_hash_handle;
971
972#endif /* UTHASH_H */
diff --git a/libs/cocos2d/Support/utlist.h b/libs/cocos2d/Support/utlist.h new file mode 100755 index 0000000..34c725b --- /dev/null +++ b/libs/cocos2d/Support/utlist.h
@@ -0,0 +1,490 @@
1/*
2Copyright (c) 2007-2010, Troy D. Hanson http://uthash.sourceforge.net
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
12IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
15OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22*/
23
24#ifndef UTLIST_H
25#define UTLIST_H
26
27#define UTLIST_VERSION 1.9.1
28
29/*
30 * This file contains macros to manipulate singly and doubly-linked lists.
31 *
32 * 1. LL_ macros: singly-linked lists.
33 * 2. DL_ macros: doubly-linked lists.
34 * 3. CDL_ macros: circular doubly-linked lists.
35 *
36 * To use singly-linked lists, your structure must have a "next" pointer.
37 * To use doubly-linked lists, your structure must "prev" and "next" pointers.
38 * Either way, the pointer to the head of the list must be initialized to NULL.
39 *
40 * ----------------.EXAMPLE -------------------------
41 * struct item {
42 * int id;
43 * struct item *prev, *next;
44 * }
45 *
46 * struct item *list = NULL:
47 *
48 * int main() {
49 * struct item *item;
50 * ... allocate and populate item ...
51 * DL_APPEND(list, item);
52 * }
53 * --------------------------------------------------
54 *
55 * For doubly-linked lists, the append and delete macros are O(1)
56 * For singly-linked lists, append and delete are O(n) but prepend is O(1)
57 * The sort macro is O(n log(n)) for all types of single/double/circular lists.
58 */
59
60/* These macros use decltype or the earlier __typeof GNU extension.
61 As decltype is only available in newer compilers (VS2010 or gcc 4.3+
62 when compiling c++ code), this code uses whatever method is needed
63 or, for VS2008 where neither is available, uses casting workarounds. */
64#ifdef _MSC_VER /* MS compiler */
65#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
66#define LDECLTYPE(x) decltype(x)
67#else /* VS2008 or older (or VS2010 in C mode) */
68#define NO_DECLTYPE
69#define LDECLTYPE(x) char*
70#endif
71#else /* GNU, Sun and other compilers */
72#define LDECLTYPE(x) __typeof(x)
73#endif
74
75/* for VS2008 we use some workarounds to get around the lack of decltype,
76 * namely, we always reassign our tmp variable to the list head if we need
77 * to dereference its prev/next pointers, and save/restore the real head.*/
78#ifdef NO_DECLTYPE
79#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
80#define _NEXT(elt,list) ((char*)((list)->next))
81#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
82#define _PREV(elt,list) ((char*)((list)->prev))
83#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
84#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
85#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
86#else
87#define _SV(elt,list)
88#define _NEXT(elt,list) ((elt)->next)
89#define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
90#define _PREV(elt,list) ((elt)->prev)
91#define _PREVASGN(elt,list,to) ((elt)->prev)=(to)
92#define _RS(list)
93#define _CASTASGN(a,b) (a)=(b)
94#endif
95
96/******************************************************************************
97 * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
98 * Unwieldy variable names used here to avoid shadowing passed-in variables. *
99 *****************************************************************************/
100#define LL_SORT(list, cmp) \
101do { \
102 LDECLTYPE(list) _ls_p; \
103 LDECLTYPE(list) _ls_q; \
104 LDECLTYPE(list) _ls_e; \
105 LDECLTYPE(list) _ls_tail; \
106 LDECLTYPE(list) _ls_oldhead; \
107 LDECLTYPE(list) _tmp; \
108 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
109 if (list) { \
110 _ls_insize = 1; \
111 _ls_looping = 1; \
112 while (_ls_looping) { \
113 _CASTASGN(_ls_p,list); \
114 _CASTASGN(_ls_oldhead,list); \
115 list = NULL; \
116 _ls_tail = NULL; \
117 _ls_nmerges = 0; \
118 while (_ls_p) { \
119 _ls_nmerges++; \
120 _ls_q = _ls_p; \
121 _ls_psize = 0; \
122 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
123 _ls_psize++; \
124 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
125 if (!_ls_q) break; \
126 } \
127 _ls_qsize = _ls_insize; \
128 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
129 if (_ls_psize == 0) { \
130 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
131 } else if (_ls_qsize == 0 || !_ls_q) { \
132 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
133 } else if (cmp(_ls_p,_ls_q) <= 0) { \
134 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
135 } else { \
136 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
137 } \
138 if (_ls_tail) { \
139 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
140 } else { \
141 _CASTASGN(list,_ls_e); \
142 } \
143 _ls_tail = _ls_e; \
144 } \
145 _ls_p = _ls_q; \
146 } \
147 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
148 if (_ls_nmerges <= 1) { \
149 _ls_looping=0; \
150 } \
151 _ls_insize *= 2; \
152 } \
153 } else _tmp=NULL; /* quiet gcc unused variable warning */ \
154} while (0)
155
156#define DL_SORT(list, cmp) \
157do { \
158 LDECLTYPE(list) _ls_p; \
159 LDECLTYPE(list) _ls_q; \
160 LDECLTYPE(list) _ls_e; \
161 LDECLTYPE(list) _ls_tail; \
162 LDECLTYPE(list) _ls_oldhead; \
163 LDECLTYPE(list) _tmp; \
164 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
165 if (list) { \
166 _ls_insize = 1; \
167 _ls_looping = 1; \
168 while (_ls_looping) { \
169 _CASTASGN(_ls_p,list); \
170 _CASTASGN(_ls_oldhead,list); \
171 list = NULL; \
172 _ls_tail = NULL; \
173 _ls_nmerges = 0; \
174 while (_ls_p) { \
175 _ls_nmerges++; \
176 _ls_q = _ls_p; \
177 _ls_psize = 0; \
178 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
179 _ls_psize++; \
180 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
181 if (!_ls_q) break; \
182 } \
183 _ls_qsize = _ls_insize; \
184 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
185 if (_ls_psize == 0) { \
186 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
187 } else if (_ls_qsize == 0 || !_ls_q) { \
188 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
189 } else if (cmp(_ls_p,_ls_q) <= 0) { \
190 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
191 } else { \
192 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
193 } \
194 if (_ls_tail) { \
195 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
196 } else { \
197 _CASTASGN(list,_ls_e); \
198 } \
199 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
200 _ls_tail = _ls_e; \
201 } \
202 _ls_p = _ls_q; \
203 } \
204 _CASTASGN(list->prev, _ls_tail); \
205 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
206 if (_ls_nmerges <= 1) { \
207 _ls_looping=0; \
208 } \
209 _ls_insize *= 2; \
210 } \
211 } else _tmp=NULL; /* quiet gcc unused variable warning */ \
212} while (0)
213
214#define CDL_SORT(list, cmp) \
215do { \
216 LDECLTYPE(list) _ls_p; \
217 LDECLTYPE(list) _ls_q; \
218 LDECLTYPE(list) _ls_e; \
219 LDECLTYPE(list) _ls_tail; \
220 LDECLTYPE(list) _ls_oldhead; \
221 LDECLTYPE(list) _tmp; \
222 LDECLTYPE(list) _tmp2; \
223 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
224 if (list) { \
225 _ls_insize = 1; \
226 _ls_looping = 1; \
227 while (_ls_looping) { \
228 _CASTASGN(_ls_p,list); \
229 _CASTASGN(_ls_oldhead,list); \
230 list = NULL; \
231 _ls_tail = NULL; \
232 _ls_nmerges = 0; \
233 while (_ls_p) { \
234 _ls_nmerges++; \
235 _ls_q = _ls_p; \
236 _ls_psize = 0; \
237 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
238 _ls_psize++; \
239 _SV(_ls_q,list); \
240 if (_NEXT(_ls_q,list) == _ls_oldhead) { \
241 _ls_q = NULL; \
242 } else { \
243 _ls_q = _NEXT(_ls_q,list); \
244 } \
245 _RS(list); \
246 if (!_ls_q) break; \
247 } \
248 _ls_qsize = _ls_insize; \
249 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
250 if (_ls_psize == 0) { \
251 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
252 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
253 } else if (_ls_qsize == 0 || !_ls_q) { \
254 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
255 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
256 } else if (cmp(_ls_p,_ls_q) <= 0) { \
257 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
258 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
259 } else { \
260 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
261 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
262 } \
263 if (_ls_tail) { \
264 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
265 } else { \
266 _CASTASGN(list,_ls_e); \
267 } \
268 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
269 _ls_tail = _ls_e; \
270 } \
271 _ls_p = _ls_q; \
272 } \
273 _CASTASGN(list->prev,_ls_tail); \
274 _CASTASGN(_tmp2,list); \
275 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
276 if (_ls_nmerges <= 1) { \
277 _ls_looping=0; \
278 } \
279 _ls_insize *= 2; \
280 } \
281 } else _tmp=NULL; /* quiet gcc unused variable warning */ \
282} while (0)
283
284/******************************************************************************
285 * singly linked list macros (non-circular) *
286 *****************************************************************************/
287#define LL_PREPEND(head,add) \
288do { \
289 (add)->next = head; \
290 head = add; \
291} while (0)
292
293#define LL_APPEND(head,add) \
294do { \
295 LDECLTYPE(head) _tmp; \
296 (add)->next=NULL; \
297 if (head) { \
298 _tmp = head; \
299 while (_tmp->next) { _tmp = _tmp->next; } \
300 _tmp->next=(add); \
301 } else { \
302 (head)=(add); \
303 } \
304} while (0)
305
306#define LL_DELETE(head,del) \
307do { \
308 LDECLTYPE(head) _tmp; \
309 if ((head) == (del)) { \
310 (head)=(head)->next; \
311 } else { \
312 _tmp = head; \
313 while (_tmp->next && (_tmp->next != (del))) { \
314 _tmp = _tmp->next; \
315 } \
316 if (_tmp->next) { \
317 _tmp->next = ((del)->next); \
318 } \
319 } \
320} while (0)
321
322/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
323#define LL_APPEND_VS2008(head,add) \
324do { \
325 if (head) { \
326 (add)->next = head; /* use add->next as a temp variable */ \
327 while ((add)->next->next) { (add)->next = (add)->next->next; } \
328 (add)->next->next=(add); \
329 } else { \
330 (head)=(add); \
331 } \
332 (add)->next=NULL; \
333} while (0)
334
335#define LL_DELETE_VS2008(head,del) \
336do { \
337 if ((head) == (del)) { \
338 (head)=(head)->next; \
339 } else { \
340 char *_tmp = (char*)(head); \
341 while (head->next && (head->next != (del))) { \
342 head = head->next; \
343 } \
344 if (head->next) { \
345 head->next = ((del)->next); \
346 } \
347 { \
348 char **_head_alias = (char**)&(head); \
349 *_head_alias = _tmp; \
350 } \
351 } \
352} while (0)
353#ifdef NO_DECLTYPE
354#undef LL_APPEND
355#define LL_APPEND LL_APPEND_VS2008
356#undef LL_DELETE
357#define LL_DELETE LL_DELETE_VS2008
358#endif
359/* end VS2008 replacements */
360
361#define LL_FOREACH(head,el) \
362 for(el=head;el;el=el->next)
363
364#define LL_FOREACH_SAFE(head,el,tmp) \
365 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
366
367#define LL_SEARCH_SCALAR(head,out,field,val) \
368do { \
369 LL_FOREACH(head,out) { \
370 if ((out)->field == (val)) break; \
371 } \
372} while(0)
373
374#define LL_SEARCH(head,out,elt,cmp) \
375do { \
376 LL_FOREACH(head,out) { \
377 if ((cmp(out,elt))==0) break; \
378 } \
379} while(0)
380
381/******************************************************************************
382 * doubly linked list macros (non-circular) *
383 *****************************************************************************/
384#define DL_PREPEND(head,add) \
385do { \
386 (add)->next = head; \
387 if (head) { \
388 (add)->prev = (head)->prev; \
389 (head)->prev = (add); \
390 } else { \
391 (add)->prev = (add); \
392 } \
393 (head) = (add); \
394} while (0)
395
396#define DL_APPEND(head,add) \
397do { \
398 if (head) { \
399 (add)->prev = (head)->prev; \
400 (head)->prev->next = (add); \
401 (head)->prev = (add); \
402 (add)->next = NULL; \
403 } else { \
404 (head)=(add); \
405 (head)->prev = (head); \
406 (head)->next = NULL; \
407 } \
408} while (0);
409
410#define DL_DELETE(head,del) \
411do { \
412 if ((del)->prev == (del)) { \
413 (head)=NULL; \
414 } else if ((del)==(head)) { \
415 (del)->next->prev = (del)->prev; \
416 (head) = (del)->next; \
417 } else { \
418 (del)->prev->next = (del)->next; \
419 if ((del)->next) { \
420 (del)->next->prev = (del)->prev; \
421 } else { \
422 (head)->prev = (del)->prev; \
423 } \
424 } \
425} while (0);
426
427
428#define DL_FOREACH(head,el) \
429 for(el=head;el;el=el->next)
430
431/* this version is safe for deleting the elements during iteration */
432#define DL_FOREACH_SAFE(head,el,tmp) \
433 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
434
435/* these are identical to their singly-linked list counterparts */
436#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
437#define DL_SEARCH LL_SEARCH
438
439/******************************************************************************
440 * circular doubly linked list macros *
441 *****************************************************************************/
442#define CDL_PREPEND(head,add) \
443do { \
444 if (head) { \
445 (add)->prev = (head)->prev; \
446 (add)->next = (head); \
447 (head)->prev = (add); \
448 (add)->prev->next = (add); \
449 } else { \
450 (add)->prev = (add); \
451 (add)->next = (add); \
452 } \
453(head)=(add); \
454} while (0)
455
456#define CDL_DELETE(head,del) \
457do { \
458 if ( ((head)==(del)) && ((head)->next == (head))) { \
459 (head) = 0L; \
460 } else { \
461 (del)->next->prev = (del)->prev; \
462 (del)->prev->next = (del)->next; \
463 if ((del) == (head)) (head)=(del)->next; \
464 } \
465} while (0);
466
467#define CDL_FOREACH(head,el) \
468 for(el=head;el;el=(el->next==head ? 0L : el->next))
469
470#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
471 for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
472 (el) && ((tmp2)=(el)->next, 1); \
473 ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
474
475#define CDL_SEARCH_SCALAR(head,out,field,val) \
476do { \
477 CDL_FOREACH(head,out) { \
478 if ((out)->field == (val)) break; \
479 } \
480} while(0)
481
482#define CDL_SEARCH(head,out,elt,cmp) \
483do { \
484 CDL_FOREACH(head,out) { \
485 if ((cmp(out,elt))==0) break; \
486 } \
487} while(0)
488
489#endif /* UTLIST_H */
490