mirror of
https://github.com/gnustep/libs-performance.git
synced 2025-02-19 10:01:20 +00:00
Some tidyups
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/performance/trunk@23634 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
05cebfc22b
commit
bfe4fb8df2
5 changed files with 182 additions and 85 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2006-09-27 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* GNUmakefile:
|
||||||
|
* GSIndexedSkipList.m:
|
||||||
|
* GSSkipMutableArray.h:
|
||||||
|
* GSSkipMutableArray.m:
|
||||||
|
Minor fix to (hopefully) build on windows.
|
||||||
|
Hide implementation details.
|
||||||
|
Add convenience method (to create skiplist) to NSMutableArray.
|
||||||
|
Some reformatting for coding standards.
|
||||||
|
|
||||||
2006-09-27 Matt Rice <ratmice@yahoo.com>
|
2006-09-27 Matt Rice <ratmice@yahoo.com>
|
||||||
|
|
||||||
* GSSkipMutableArray.[hm]: New NSMutableArray subclass.
|
* GSSkipMutableArray.[hm]: New NSMutableArray subclass.
|
||||||
|
|
|
@ -26,7 +26,6 @@ Performance_HEADER_FILES += \
|
||||||
GSCache.h \
|
GSCache.h \
|
||||||
GSThroughput.h \
|
GSThroughput.h \
|
||||||
GSTicker.h \
|
GSTicker.h \
|
||||||
GSIndexedSkipList.h \
|
|
||||||
GSSkipMutableArray.h \
|
GSSkipMutableArray.h \
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "GSIndexedSkipList.h"
|
#include "GSIndexedSkipList.h"
|
||||||
|
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
#include <cstdlib.h> /* declares rand() */
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PrettyErr(x) do { fprintf(stderr, "%s:%i: %s\n",__FILE__, __LINE__, x); exit(EXIT_FAILURE); } while (0)
|
#define PrettyErr(x) do { fprintf(stderr, "%s:%i: %s\n",__FILE__, __LINE__, x); exit(EXIT_FAILURE); } while (0)
|
||||||
|
|
||||||
GSISLNode GSISLNil;
|
GSISLNode GSISLNil;
|
||||||
|
@ -107,6 +111,7 @@ int GSISLRandomLevel()
|
||||||
{
|
{
|
||||||
int level = 0;
|
int level = 0;
|
||||||
static int p = RAND_MAX / 4;
|
static int p = RAND_MAX / 4;
|
||||||
|
|
||||||
while (rand() < p && level < GSISLMaxLevel)
|
while (rand() < p && level < GSISLMaxLevel)
|
||||||
{
|
{
|
||||||
level++;
|
level++;
|
||||||
|
@ -141,7 +146,7 @@ void GSISLInsertItemAtIndex(GSISList l, GSISLValueType value,
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
while (q = p->forward[k].next,
|
while (q = p->forward[k].next,
|
||||||
q != GSISLNil && depth + p->forward[k].delta < index + 1)
|
q != GSISLNil && depth + p->forward[k].delta < index + 1)
|
||||||
{
|
{
|
||||||
depth += p->forward[k].delta;
|
depth += p->forward[k].delta;
|
||||||
p = q;
|
p = q;
|
||||||
|
@ -234,7 +239,7 @@ GSISLValueType GSISLRemoveItemAtIndex(GSISList l, unsigned index)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
while (q = p->forward[k].next,
|
while (q = p->forward[k].next,
|
||||||
q != GSISLNil && depth + p->forward[k].delta < index + 1)
|
q != GSISLNil && depth + p->forward[k].delta < index + 1)
|
||||||
{
|
{
|
||||||
depth += p->forward[k].delta;
|
depth += p->forward[k].delta;
|
||||||
p = q;
|
p = q;
|
||||||
|
@ -252,9 +257,9 @@ GSISLValueType GSISLRemoveItemAtIndex(GSISList l, unsigned index)
|
||||||
#endif
|
#endif
|
||||||
if (p->forward[k].next == q)
|
if (p->forward[k].next == q)
|
||||||
{
|
{
|
||||||
p->forward[k].delta = (q->forward[k].next == GSISLNil)
|
p->forward[k].delta
|
||||||
? 0
|
= (q->forward[k].next == GSISLNil) ? 0
|
||||||
: p->forward[k].delta + q->forward[k].delta - 1;
|
: p->forward[k].delta + q->forward[k].delta - 1;
|
||||||
|
|
||||||
p->forward[k].next = q->forward[k].next;
|
p->forward[k].next = q->forward[k].next;
|
||||||
}
|
}
|
||||||
|
@ -305,7 +310,8 @@ GSISLValueType GSISLItemAtIndex(GSISList l, unsigned index)
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
while (q = p->forward[k].next, q != GSISLNil && depth + p->forward[k].delta < index + 1)
|
while (q = p->forward[k].next,
|
||||||
|
q != GSISLNil && depth + p->forward[k].delta < index + 1)
|
||||||
{
|
{
|
||||||
depth += p->forward[k].delta;
|
depth += p->forward[k].delta;
|
||||||
p = q;
|
p = q;
|
||||||
|
@ -319,7 +325,8 @@ GSISLValueType GSISLItemAtIndex(GSISList l, unsigned index)
|
||||||
return(q->value);
|
return(q->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
GSISLValueType GSISLReplaceItemAtIndex(GSISList l, GSISLValueType newVal, unsigned index)
|
GSISLValueType
|
||||||
|
GSISLReplaceItemAtIndex(GSISList l, GSISLValueType newVal, unsigned index)
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
unsigned depth = 0;
|
unsigned depth = 0;
|
||||||
|
@ -345,7 +352,7 @@ GSISLValueType GSISLReplaceItemAtIndex(GSISList l, GSISLValueType newVal, unsign
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
while (q = p->forward[k].next,
|
while (q = p->forward[k].next,
|
||||||
q != GSISLNil && depth + p->forward[k].delta < index + 1)
|
q != GSISLNil && depth + p->forward[k].delta < index + 1)
|
||||||
{
|
{
|
||||||
depth += p->forward[k].delta;
|
depth += p->forward[k].delta;
|
||||||
p = q;
|
p = q;
|
||||||
|
|
|
@ -21,49 +21,64 @@
|
||||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||||
*/
|
*/
|
||||||
#include <Foundation/NSArray.h>
|
#include <Foundation/NSArray.h>
|
||||||
#include <GSIndexedSkipList.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
<p>A NSMutableArray subclass which uses a skip list variant for it's underlying
|
<p>An NSMutableArray subclass which uses a skip list variant for
|
||||||
data structure.</p>
|
it's underlying data structure.
|
||||||
|
</p>
|
||||||
<p>while a skip list is typically sorted and represents a dictionary.
|
<p>While a skip list is typically sorted and represents a dictionary.
|
||||||
the indexed skip list is sorted by index and maintains deltas to represent
|
the indexed skip list is sorted by index and maintains deltas to represent
|
||||||
the distance between linked nodes.</p>
|
the distance between linked nodes.
|
||||||
|
</p>
|
||||||
<p><code>the underlying data structure looks much like the figure below:<br/>
|
<p>The underlying data structure looks much like the figure below:
|
||||||
index -> HEAD 1 2 3 4 5 6 TAIL<br/>
|
</p>
|
||||||
5| ---------------------> # ------> #<br/>
|
<example>
|
||||||
3| -----------> 2 ------> # ------> #<br/>
|
index -> HEAD 1 2 3 4 5 6 TAIL
|
||||||
1| -> 1 -> 1 -> 1 -> 1 -> 1 -> # -> #<br/></code></p>
|
5| ---------------------> # ------> #
|
||||||
|
3| -----------> 2 ------> # ------> #
|
||||||
|
1| -> 1 -> 1 -> 1 -> 1 -> 1 -> # -> #
|
||||||
|
</example>
|
||||||
|
|
||||||
<p>where the numbers represent how many indexes it is to the next node
|
<p>Where the numbers represent how many indexes it is to the next node
|
||||||
of the appropriate level. The bottom level always points to the next node.</p>
|
of the appropriate level. The bottom level always points to the next node.</p>
|
||||||
|
|
||||||
<p>finding a specific index starts at the top level, until the current
|
<p>Finding a specific index starts at the top level, until the current
|
||||||
depth + the next nodes delta is larger than wanted index, then it goes down
|
depth + the next nodes delta is larger than wanted index, then it goes down
|
||||||
1 level, and repeats until it finds the wanted index.</p>
|
1 level, and repeats until it finds the wanted index.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>addition and removal of indexes requires an update of the deltas of nodes
|
<p>Addition and removal of indexes requires an update of the deltas of nodes
|
||||||
which begin before, and end after the wanted index,
|
which begin before, and end after the wanted index,
|
||||||
these are the places where it goes down a level.</p>
|
these are the places where it goes down a level.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>the rationale behind it was where a linked list based mutable array will
|
<p>The rationale behind it was where a linked list based mutable array will
|
||||||
quickly add and remove elements, it may perform poorly at accessing any
|
quickly add and remove elements, it may perform poorly at accessing any
|
||||||
random index (because it must traverse the entire list to get to the index).</p>
|
random index (because it must traverse the entire list to get to the index).
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>and while a c array based mutable array will perform good at random index
|
<p>While a C array based mutable array will perform good at random index
|
||||||
access it may perform poorly at adding and removing indexes
|
access it may perform poorly at adding and removing indexes
|
||||||
(because it must move all items after the altered index).</p>
|
(because it must move all items after the altered index).
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>so while a SkipMutableArray may not outperform a linked list or a c array
|
<p>While a GSSkipMutableArray may not outperform a linked list or a
|
||||||
mutable array at their specific strengths, it attempts to not suffer from
|
C array based mutable array at their specific strengths, it attempts
|
||||||
either of their weaknesses, at the cost of additional memory overhead..</p>
|
to not suffer from either of their weaknesses, at the cost of additional
|
||||||
|
memory overhead.
|
||||||
|
</p>
|
||||||
*/
|
*/
|
||||||
@interface SkipMutableArray : NSMutableArray
|
@interface GSSkipMutableArray : NSMutableArray
|
||||||
{
|
@end
|
||||||
GSISList l;
|
|
||||||
}
|
/**
|
||||||
|
* This category just provides a simpole convenience method to obtain
|
||||||
|
* a GSSkipMutableArray instance;
|
||||||
|
*/
|
||||||
|
@interface NSMutableArray (GSSkipMutableArray)
|
||||||
|
/**
|
||||||
|
* Creates and returns an autoreleased GSSkipMutableArray.
|
||||||
|
*/
|
||||||
|
+ (GSSkipMutableArray*) skipArray;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -21,43 +21,76 @@
|
||||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "GSSkipMutableArray.h"
|
|
||||||
#include <Foundation/NSException.h>
|
#include <Foundation/NSException.h>
|
||||||
#include <Foundation/NSValue.h>
|
#include <Foundation/NSValue.h>
|
||||||
#include <Foundation/NSEnumerator.h>
|
#include <Foundation/NSEnumerator.h>
|
||||||
|
|
||||||
@interface SkipMutableArray(Private)
|
#include "GSSkipMutableArray.h"
|
||||||
|
#include "GSIndexedSkipList.h"
|
||||||
|
|
||||||
|
static Class abstractClass = 0;
|
||||||
|
static Class concreteClass = 0;
|
||||||
|
|
||||||
|
@interface GSConcreteSkipArray : GSSkipMutableArray
|
||||||
|
{
|
||||||
|
GSISList l;
|
||||||
|
}
|
||||||
- (GSISList) _list;
|
- (GSISList) _list;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SkipMutableArray(Private)
|
@implementation NSMutableArray (GSSkipMutableArray)
|
||||||
- (GSISList) _list
|
+ (GSSkipMutableArray*) skipArray
|
||||||
{
|
{
|
||||||
return l;
|
return [GSSkipMutableArray array];
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface SkipMutableArrayEnumerator : NSEnumerator
|
@implementation GSSkipMutableArray
|
||||||
|
+ (id) allocWithZone: (NSZone*)z
|
||||||
|
{
|
||||||
|
if (self == abstractClass)
|
||||||
|
{
|
||||||
|
return [concreteClass allocWithZone: z];
|
||||||
|
}
|
||||||
|
return [super allocWithZone: z];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void) initialize
|
||||||
|
{
|
||||||
|
if (abstractClass == 0)
|
||||||
|
{
|
||||||
|
abstractClass = [GSSkipMutableArray class];
|
||||||
|
concreteClass = [GSConcreteSkipArray class];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@interface GSConcreteSkipArrayEnumerator : NSEnumerator
|
||||||
{
|
{
|
||||||
GSISLNode node;
|
GSISLNode node;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SkipMutableArrayEnumerator
|
@implementation GSConcreteSkipArrayEnumerator
|
||||||
- (id) initWithArray:(NSArray *)arr
|
- (id) initWithArray: (NSArray *)arr
|
||||||
{
|
{
|
||||||
if (![arr isKindOfClass:[SkipMutableArray class]])
|
if (![arr isKindOfClass: [GSConcreteSkipArray class]])
|
||||||
{
|
{
|
||||||
[[NSException exceptionWithName:NSInternalInconsistencyException reason:@"not a SkipMutableArray" userInfo:nil] raise];
|
[[NSException exceptionWithName: NSInternalInconsistencyException
|
||||||
}
|
reason: @"not a GSConcreteSkipArray"
|
||||||
|
userInfo: nil] raise];
|
||||||
|
}
|
||||||
self = [super init];
|
self = [super init];
|
||||||
node = [(SkipMutableArray *)arr _list]->header->forward[0].next;
|
node = [(GSConcreteSkipArray *)arr _list]->header->forward[0].next;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) nextObject
|
- (id) nextObject
|
||||||
{
|
{
|
||||||
id foo = node->value;
|
id foo = node->value;
|
||||||
|
|
||||||
if (node == GSISLNil)
|
if (node == GSISLNil)
|
||||||
return nil;
|
return nil;
|
||||||
node = node->forward[0].next;
|
node = node->forward[0].next;
|
||||||
|
@ -65,7 +98,13 @@
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SkipMutableArray : NSMutableArray
|
@implementation GSConcreteSkipArray
|
||||||
|
|
||||||
|
- (GSISList) _list
|
||||||
|
{
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
- (void) _raiseRangeExceptionWithIndex: (unsigned)index from: (SEL)sel
|
- (void) _raiseRangeExceptionWithIndex: (unsigned)index from: (SEL)sel
|
||||||
{
|
{
|
||||||
NSDictionary *info;
|
NSDictionary *info;
|
||||||
|
@ -90,8 +129,7 @@
|
||||||
GSISLInitialize();
|
GSISLInitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (id) initWithObjects: (id *)objects count: (unsigned) count
|
||||||
- (id) initWithObjects:(id *)objects count:(unsigned) count
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
self = [super init];
|
self = [super init];
|
||||||
|
@ -101,9 +139,9 @@
|
||||||
l = GSISLInitList([self zone]);
|
l = GSISLInitList([self zone]);
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
GSISLInsertItemAtIndex(l, RETAIN(objects[i]), i);
|
GSISLInsertItemAtIndex(l, RETAIN(objects[i]), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -132,9 +170,10 @@
|
||||||
} while (p != GSISLNil);
|
} while (p != GSISLNil);
|
||||||
NSZoneFree(l->zone, l->header);
|
NSZoneFree(l->zone, l->header);
|
||||||
NSZoneFree(l->zone, l);
|
NSZoneFree(l->zone, l);
|
||||||
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) insertObject:(id)object atIndex:(unsigned)index
|
- (void) insertObject: (id)object atIndex: (unsigned)index
|
||||||
{
|
{
|
||||||
if (index > l->count)
|
if (index > l->count)
|
||||||
{
|
{
|
||||||
|
@ -144,7 +183,7 @@
|
||||||
GSISLInsertItemAtIndex(l, RETAIN(object), index);
|
GSISLInsertItemAtIndex(l, RETAIN(object), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) objectAtIndex:(unsigned)index
|
- (id) objectAtIndex: (unsigned)index
|
||||||
{
|
{
|
||||||
if (index >= l->count)
|
if (index >= l->count)
|
||||||
{
|
{
|
||||||
|
@ -154,7 +193,7 @@
|
||||||
return GSISLItemAtIndex(l, index);
|
return GSISLItemAtIndex(l, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeObjectAtIndex:(unsigned) index
|
- (void) removeObjectAtIndex: (unsigned) index
|
||||||
{
|
{
|
||||||
if (index >= l->count)
|
if (index >= l->count)
|
||||||
{
|
{
|
||||||
|
@ -164,7 +203,7 @@
|
||||||
RELEASE(GSISLRemoveItemAtIndex(l, index));
|
RELEASE(GSISLRemoveItemAtIndex(l, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) addObject:(id)obj
|
- (void) addObject: (id)obj
|
||||||
{
|
{
|
||||||
GSISLInsertItemAtIndex(l, RETAIN(obj), l->count);
|
GSISLInsertItemAtIndex(l, RETAIN(obj), l->count);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +213,7 @@
|
||||||
return l->count;
|
return l->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) replaceObjectAtIndex:(unsigned)index withObject:(id)obj
|
- (void) replaceObjectAtIndex: (unsigned)index withObject: (id)obj
|
||||||
{
|
{
|
||||||
RELEASE(GSISLReplaceItemAtIndex(l, RETAIN(obj), index));
|
RELEASE(GSISLReplaceItemAtIndex(l, RETAIN(obj), index));
|
||||||
}
|
}
|
||||||
|
@ -183,50 +222,77 @@
|
||||||
{
|
{
|
||||||
id e;
|
id e;
|
||||||
|
|
||||||
e = [SkipMutableArrayEnumerator allocWithZone: NSDefaultMallocZone()];
|
e = [GSConcreteSkipArrayEnumerator
|
||||||
|
allocWithZone: NSDefaultMallocZone()];
|
||||||
e = [e initWithArray: self];
|
e = [e initWithArray: self];
|
||||||
return AUTORELEASE(e);
|
return AUTORELEASE(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns an in an NSString suitable for running through graphviz,
|
/* returns an in an NSString suitable for running through graphviz,
|
||||||
* with the graph named 'graphName'
|
* with the graph named 'graphName'
|
||||||
*/
|
*/
|
||||||
- (NSString *) _makeGraphOfInternalLayoutNamed:(NSString *)graphName
|
- (NSString *) _makeGraphOfInternalLayoutNamed: (NSString *)graphName
|
||||||
{
|
{
|
||||||
GSISLNode p;
|
GSISLNode p;
|
||||||
unsigned k, i;
|
unsigned k, i;
|
||||||
|
NSMutableDictionary *values;
|
||||||
|
NSMutableArray *edges;
|
||||||
|
NSMutableString *graph;
|
||||||
|
NSArray *tmp;
|
||||||
|
|
||||||
p = l->header;
|
p = l->header;
|
||||||
k = l->level;
|
k = l->level;
|
||||||
NSMutableString *graph = [[NSMutableString alloc] init];
|
|
||||||
[graph appendString:[NSString stringWithFormat:@"digraph %@ {\n", graphName]];
|
[graph appendString:
|
||||||
[graph appendString:@"graph [rankdir = LR];\n"];
|
[NSString stringWithFormat: @"digraph %@ {\n", graphName]];
|
||||||
[graph appendString:@"node [shape = record];\n"];
|
[graph appendString: @"graph [rankdir = LR];\n"];
|
||||||
NSMutableDictionary *values = [[NSMutableDictionary alloc] init];
|
[graph appendString: @"node [shape = record];\n"];
|
||||||
NSMutableArray *edges = [[NSMutableArray alloc] init];
|
values = [[NSMutableDictionary alloc] init];
|
||||||
NSArray *tmp;
|
edges = [[NSMutableArray alloc] init];
|
||||||
[values setObject:[NSMutableString stringWithFormat:@"\"%p\" [label = \"%p (NIL) |{ <delta0> 0 | <forward0> }",GSISLNil, GSISLNil] forKey:[NSString stringWithFormat:@"%p", GSISLNil]];
|
[values setObject:
|
||||||
|
[NSMutableString stringWithFormat:
|
||||||
|
@"\"%p\" [label = \"%p (NIL) |{ <delta0> 0 | <forward0> }",
|
||||||
|
GSISLNil, GSISLNil]
|
||||||
|
forKey: [NSString stringWithFormat: @"%p", GSISLNil]];
|
||||||
for (k = 0; k < l->level + 1; k++)
|
for (k = 0; k < l->level + 1; k++)
|
||||||
{
|
{
|
||||||
for (p = l->header; p != GSISLNil; p = p->forward[k].next)
|
for (p = l->header; p != GSISLNil; p = p->forward[k].next)
|
||||||
{
|
{
|
||||||
NSString *value = [NSString stringWithFormat:@"%p", p];
|
NSString *value;
|
||||||
NSMutableString *foo = [values objectForKey:value];
|
NSMutableString *foo;
|
||||||
|
|
||||||
|
value = [NSString stringWithFormat: @"%p", p];
|
||||||
|
foo = [values objectForKey: value];
|
||||||
if (foo == nil)
|
if (foo == nil)
|
||||||
{
|
{
|
||||||
foo = [[NSMutableString alloc] init];
|
foo = [[NSMutableString alloc] init];
|
||||||
[foo appendString:[NSString stringWithFormat:@"\"%p\" [label = \"%p%@ |{ <delta%i> %i | <forward%i> }", p, p, p == l->header ? @"(HEADER)" : @"", k, p->forward[k].delta, k]];
|
[foo appendString:
|
||||||
|
[NSString stringWithFormat:
|
||||||
|
@"\"%p\" [label = \"%p%@ |{ <delta%i> %i | <forward%i> }",
|
||||||
|
p, p, p == l->header ? @"(HEADER)" : @"", k,
|
||||||
|
p->forward[k].delta, k]];
|
||||||
if (p != GSISLNil)
|
if (p != GSISLNil)
|
||||||
[edges addObject:[NSString stringWithFormat:@"\"%p\":forward%i -> \"%p\":delta%i;\n",p,k, p->forward[k].next,p->forward[k].next == GSISLNil ? 0 : k]];
|
[edges addObject:
|
||||||
[values setObject:foo forKey:value];
|
[NSString stringWithFormat:
|
||||||
|
@"\"%p\": forward%i -> \"%p\": delta%i;\n",
|
||||||
|
p, k, p->forward[k].next,
|
||||||
|
p->forward[k].next == GSISLNil ? 0 : k]];
|
||||||
|
[values setObject: foo forKey: value];
|
||||||
RELEASE(foo);
|
RELEASE(foo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[foo appendString:[NSString stringWithFormat:@"|{ <delta%i> %i | <forward%i> }", k, p->forward[k].delta, k]];
|
[foo appendString:
|
||||||
|
[NSString stringWithFormat:
|
||||||
|
@"|{ <delta%i> %i | <forward%i> }",
|
||||||
|
k, p->forward[k].delta, k]];
|
||||||
if (p != GSISLNil)
|
if (p != GSISLNil)
|
||||||
[edges addObject:[NSString stringWithFormat:@"\"%p\":forward%i -> \"%p\":delta%i;\n",p,k, p->forward[k].next, p->forward[k].next == GSISLNil ? 0 : k]];
|
[edges addObject:
|
||||||
[values setObject:foo forKey:value];
|
[NSString stringWithFormat:
|
||||||
|
@"\"%p\": forward%i -> \"%p\": delta%i;\n",
|
||||||
|
p, k, p->forward[k].next,
|
||||||
|
p->forward[k].next == GSISLNil ? 0 : k]];
|
||||||
|
[values setObject: foo forKey: value];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,18 +300,17 @@
|
||||||
tmp = [values allKeys];
|
tmp = [values allKeys];
|
||||||
for (i = 0; i < [tmp count]; i++)
|
for (i = 0; i < [tmp count]; i++)
|
||||||
{
|
{
|
||||||
[graph appendString:[values objectForKey:[tmp objectAtIndex:i]]];
|
[graph appendString: [values objectForKey: [tmp objectAtIndex: i]]];
|
||||||
[graph appendString:@"\"];\n"];
|
[graph appendString: @"\"];\n"];
|
||||||
}
|
}
|
||||||
for (i = 0; i < [edges count]; i++)
|
for (i = 0; i < [edges count]; i++)
|
||||||
{
|
{
|
||||||
[graph appendString:[edges objectAtIndex:i]];
|
[graph appendString: [edges objectAtIndex: i]];
|
||||||
}
|
}
|
||||||
[graph appendString:@"}\n"];
|
[graph appendString: @"}\n"];
|
||||||
RELEASE(values);
|
RELEASE(values);
|
||||||
RELEASE(edges);
|
RELEASE(edges);
|
||||||
return AUTORELEASE(graph);
|
return AUTORELEASE(graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
Loading…
Reference in a new issue