Reading in a 5000 line text file on the Iphone
- by howsyourface
Gday, I am trying to create a tiled map for my game, i have had this previously working using other xml methods but i had memory leaks and all sorts of errors. However i had a map load time of about 2.5 - 3 seconds.
So i rewrote all of the code using NSMutableStrings and NSStrings. After my best attempt at optomizing it i had a map load time of 10 - 11 seconds, which is far too slow.
So i have now rewritten the code using char* arrays, only to now have a load time of 18 seconds -_-.
Here is the latest code, i don't know much c so i could have easily botched the whole thing up.
FILE* file = fopen(a, "r");
fseek(file, 0L, SEEK_END);
length = ftell(file);
fseek(file,0L, SEEK_SET);
char fileText[length +1];
char buffer[1024];// = malloc(1024);
while(fgets(buffer, 1024, file) != NULL)
{
strncat(fileText, buffer, strlen(buffer));
}
fclose(file);
[self parseMapFile:fileText];
- (void)parseMapFile:(char*)tiledXML
{
currentLayerID = 0;
currentTileSetID = 0;
tileX = 0;
tileY = 0;
int tmpGid;
NSString* tmpName;
int tmpTileWidth;
int tmpTileHeight;
int tilesetCounter = 0;
NSString* tmpLayerName;
int tmpLayerHeight;
int tmpLayerWidth;
int layerCounter = 0;
tileX = 0;
tileY = 0;
int tmpFirstGid = 0;
int x;
int index;
char* r;
int counter = 0;
while ((x = [self findSubstring:tiledXML substring:"\n"]) != 0)
{
counter ++;
char result[x + 1];
r = &result[0];
[self substringIndex:tiledXML index:x newArray:result];
tiledXML += x+2;
index = 0;
if (counter == 1)
{
continue;
}
else if (counter == 2)
{
char result1[5];
index = [self getStringBetweenStrings:r substring1:"th=\"" substring2:"\"" newArray:result1];
if (r != 0);
mapWidth = atoi(result1);
r += index +1;
index = 0;
index = [self getStringBetweenStrings:r substring1:"ht=\"" substring2:"\"" newArray:result1];
if (r != 0);
mapHeight = atoi(result1);
r += index +1;
index = 0;
index = [self getStringBetweenStrings:r substring1:"th=\"" substring2:"\"" newArray:result1];
if (r != 0);
tileWidth = atoi(result1);
r += index +1;
index = 0;
index = [self getStringBetweenStrings:r substring1:"ht=\"" substring2:"\"" newArray:result1];
if (r != 0);
tileHeight = atoi(result1);
continue;
}
char result2[50];
char result3[3];
if ((index = [self getStringBetweenStrings:r substring1:" gid=\"" substring2:"\"" newArray:result3]) != 0)
{
tmpGid = atoi(result3);
free(result2);
if(tmpGid == 0)
{
[currentLayer addTileAtX:tileX y:tileY tileSetID:-1 tileID:0 globalID:0];
}
else
{
[currentLayer addTileAtX:tileX
y:tileY
tileSetID:[currentTileSet tileSetID]
tileID:tmpGid - [currentTileSet firstGID]
globalID:tmpGid];
}
tileX ++;
if (tileX > [currentLayer layerWidth]-1)
{
tileY ++;
tileX = 0;
}
}
else if ((index = [self getStringBetweenStrings:r substring1:"tgid=\"" substring2:"\"" newArray:result2]) != 0)
{
tmpFirstGid = atoi(result2);
r += index +1;
index = 0;
index = [self getStringBetweenStrings:r substring1:"me=\"" substring2:"\"" newArray:result2];
if (r != 0);
tmpName = [NSString stringWithUTF8String:result2];
r += index +1;
index = 0;
index = [self getStringBetweenStrings:r substring1:"th=\"" substring2:"\"" newArray:result2];
if (r != 0);
tmpTileWidth = atoi(result2);
r += index +1;
index = 0;
index = [self getStringBetweenStrings:r substring1:"ht=\"" substring2:"\"" newArray:result2];
if (r != 0);
tmpTileHeight = atoi(result2);
}
else if ((index = [self getStringBetweenStrings:r substring1:"rce=\"" substring2:"\"" newArray:result2]) != 0)
{
currentTileSet = [[TileSet alloc] initWithImageNamed:[NSString stringWithUTF8String:result2] name:tmpName tileSetID:tilesetCounter firstGID:tmpFirstGid tileWidth:tmpTileWidth tileHeight:tmpTileHeight spacing:0];
[tileSets addObject:currentTileSet];
[currentTileSet release];
tilesetCounter ++;
}
else if ((index = [self getStringBetweenStrings:r substring1:"r name=\"" substring2:"\"" newArray:result2]) != 0)
{
tileX = 0;
tileY = 0;
tmpLayerName = [NSString stringWithUTF8String:result2];
r += index +1;
index = 0;
index = [self getStringBetweenStrings:r substring1:"th=\"" substring2:"\"" newArray:result2];
if (r != 0);
tmpLayerWidth = atoi(result2);
r += index +1;
index = 0;
index = [self getStringBetweenStrings:r substring1:"ht=\"" substring2:"\"" newArray:result2];
if (r != 0);
tmpLayerHeight = atoi(result2);
currentLayer = [[Layer alloc] initWithName:tmpLayerName layerID:layerCounter layerWidth:tmpLayerWidth layerHeight:tmpLayerHeight];
[layers addObject:currentLayer];
[currentLayer release];
layerCounter ++;
}
}
}
-(void)substringIndex:(char*)c index:(int)x newArray:(char*)result
{
result[0] = 0;
for (int i = 0; i < strlen(c); i++)
{
result[i] = c[i];
if (i == x)
{
result[i+1] = '\0';
break;
}
}
}
-(int)findSubstring:(char*)c substring:(char*)s
{
int sCounter = 0;
int index = 0;
int d;
for (int i = 0; i < strlen(c); i ++)
{
if (i > 500)//max line size
break;
if (c[i] == s[sCounter])
{
d = strlen(s);
sCounter ++;
if (d > sCounter)
{
}
else
{
index = i - (d);
break;
}
}
else
sCounter = 0;
}
return index;
}
-(int)getStringBetweenStrings:(char*)c substring1:(char*)s substring2:(char*)s2 newArray:(char*)result
{
int sCounter = 0;
int sCounter2 = 0;
int index = 0;
int index2 = 0;
int d;
for (int i = 0; i < strlen(c); i ++)
{
if (index != 0)
{
if (c[i] == s2[sCounter2])
{
d = strlen(s2);
sCounter2 ++;
if (d > sCounter2)
{
}
else
{
index2 = i - (d);
break;
}
}
else
sCounter2 = 0;
}
else
{
if (c[i] == s[sCounter])
{
d = strlen(s);
sCounter ++;
if (d > sCounter)
{
}
else
{
index = i;
}
}
else
sCounter = 0;
}
}
if (index != 0 && index2 != 0)
[self substringIndex:(c + index+1) index:index2-index-1 newArray:result];
return index;
}
(I know it's a lot of code to be putting in here)
I thought the by using basic char arrays i could drastically increase the performance, at least over the initial node based code that i was replacing.
Thanks for all your efforts.