Skip to content

Commit ee36dc1

Browse files
committed
foundation: reduce IO calls for tmx handling functions
1 parent 6dcfb03 commit ee36dc1

1 file changed

Lines changed: 163 additions & 94 deletions

File tree

statements.c

Lines changed: 163 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,18 +2194,11 @@ void plotvalue (char **statement)
21942194

21952195
}
21962196

2197-
21982197
void plotmapfile (char **statement)
21992198
{
22002199
// 1 2 3 4 5 6 7
22012200
// plotmapfile map_file.tmx display_mem screen_x screen_y screen_width screen_height
22022201

2203-
// Overview
2204-
// 1. open map file
2205-
// 2. create an int array of widthxheight
2206-
// 3. set each cell of the int according to the palette of the character there
2207-
// 4. run through the array and build up the data structure for plotcharloop
2208-
22092202
char datavalues[256][256];
22102203
int s, t;
22112204
int x, y, width, height;
@@ -2224,30 +2217,57 @@ void plotmapfile (char **statement)
22242217

22252218
fixfilename (statement[2]);
22262219

2227-
//open file...
2228-
FILE *fp = fopen (statement[2], "rb");
2220+
FILE *fp = fopen(statement[2], "rb");
22292221
if (!fp)
2230-
{
2231-
prerror ("plotmapfile couldn't open map file '%s' for reading", statement[2]);
2232-
}
2222+
prerror("plotmapfile couldn't open map file '%s' for reading", statement[2]);
2223+
2224+
// 1. Get file size and read entire file into memory
2225+
fseek(fp, 0, SEEK_END);
2226+
long file_size = ftell(fp);
2227+
rewind(fp);
2228+
2229+
char *file_buffer = malloc(file_size + 1);
2230+
if (file_buffer == NULL)
2231+
prerror("couldn't allocate memory to read %s", statement[2]);
22332232

2233+
if (fread(file_buffer, 1, file_size, fp) != file_size)
2234+
prerror("couldn't read %s into memory", statement[2]);
2235+
fclose(fp);
2236+
file_buffer[file_size] = '\0'; // Null-terminate the entire buffer
22342237

22352238
//our default data label...
22362239
for (t = 0; t < 256; t++)
22372240
sprintf (datavalues[t], "palette0");
2238-
//datavalues
2239-
for (;;)
2241+
2242+
// 2. Process the file from the in-memory buffer
2243+
char *current_pos = file_buffer;
2244+
char *buffer_end = file_buffer + file_size;
2245+
2246+
while (current_pos < buffer_end)
22402247
{
2241-
char line[1024];
2248+
char line[1024];
2249+
char *line_end = strchr(current_pos, '\n');
2250+
long line_len;
2251+
2252+
if (line_end) {
2253+
line_len = line_end - current_pos;
2254+
} else {
2255+
line_len = buffer_end - current_pos;
2256+
}
2257+
2258+
if (line_len >= sizeof(line)) {
2259+
prerror("line too long in map file '%s'", statement[2]);
2260+
}
2261+
2262+
memcpy(line, current_pos, line_len);
2263+
line[line_len] = '\0';
2264+
22422265
char *keyword;
22432266
char *firstgid;
22442267
char *tilename;
22452268
int gid;
22462269
int layer = 0;
22472270

2248-
if (fgets (line, 1024, fp) == NULL)
2249-
break;
2250-
22512271
keyword = strstr (line, "tileset firstgid=\"");
22522272
if (keyword != NULL)
22532273
{
@@ -2292,26 +2312,29 @@ void plotmapfile (char **statement)
22922312
{
22932313
if ((q == 999) || (palettefilenames[q][0] == 0))
22942314
{
2295-
if (passes==0)
2296-
return;
2297-
else
2298-
prerror ("plotmapfile didn't find a palette for %s", datavalues[gid]);
2315+
if (passes==0) {
2316+
// Can't error on first pass, just exit loop and function
2317+
current_pos = buffer_end;
2318+
break;
2319+
}
2320+
prerror ("plotmapfile didn't find a palette for %s", datavalues[gid]);
22992321
}
23002322

23012323
if (strcmp (palettefilenames[q], datavalues[gid]) == 0)
23022324
break;
23032325
}
2304-
2305-
palettevalues[tileindex] = graphicfilepalettes[q];
2306-
graphicmodes[tileindex] = graphicfilemodes[q];
2326+
if (q < 1000 && palettefilenames[q][0] != 0) {
2327+
palettevalues[tileindex] = graphicfilepalettes[q];
2328+
graphicmodes[tileindex] = graphicfilemodes[q];
2329+
}
23072330

23082331
tileindex++;
23092332
}
23102333

23112334
keyword = strstr (line, "<data encoding=\"");
23122335
if (keyword != NULL)
23132336
{
2314-
fclose (fp);
2337+
free(file_buffer);
23152338
keyword = keyword + 15;
23162339
for (t = 0; t < 1024; t++)
23172340
if (line[t] == '"')
@@ -2324,13 +2347,23 @@ void plotmapfile (char **statement)
23242347
layer = layer + 1;
23252348
if (layer > 1)
23262349
{
2327-
fclose (fp);
2350+
free(file_buffer);
23282351
prerror ("map file '%s' contains multiple layers", statement[2]);
23292352
}
23302353
}
2354+
2355+
if (line_end) {
2356+
current_pos = line_end + 1;
2357+
} else {
2358+
break; // End of buffer
2359+
}
23312360
}
2332-
fclose (fp);
2361+
free(file_buffer);
23332362

2363+
// If we bailed on pass 0, just return now.
2364+
if (passes == 0 && (tileindex == 0 || (palettevalues[0] == 0 && tileindex < 2))) {
2365+
return;
2366+
}
23342367

23352368
int startp;
23362369
int pmwidth, charwidth, pmx, pmy, pmemoffset, pmwidthandpalette;
@@ -2397,6 +2430,7 @@ void plotmapfile (char **statement)
23972430
templabel = templabel + 1;
23982431
}
23992432

2433+
24002434
void plotmap (char **statement)
24012435
{
24022436

@@ -3623,80 +3657,115 @@ void incmapfile (char **statement)
36233657

36243658
backupthisfile(statement[2]);
36253659

3626-
//open file...
3627-
FILE *fp = fopen (statement[2], "rb");
3660+
FILE *fp = fopen(statement[2], "rb");
36283661
if (!fp)
3629-
{
3630-
prerror ("incmapfile couldn't open map file '%s' for reading", statement[2]);
3631-
}
3662+
prerror("incmapfile couldn't open map file '%s' for reading", statement[2]);
36323663

3633-
for (;;)
3664+
// 1. Get file size and read entire file into memory
3665+
fseek(fp, 0, SEEK_END);
3666+
long file_size = ftell(fp);
3667+
rewind(fp);
3668+
3669+
char *file_buffer = malloc(file_size + 1);
3670+
if (file_buffer == NULL)
3671+
prerror("couldn't allocate memory to read %s", statement[2]);
3672+
3673+
if (fread(file_buffer, 1, file_size, fp) != file_size)
3674+
prerror("couldn't read %s into memory", statement[2]);
3675+
fclose(fp);
3676+
file_buffer[file_size] = '\0'; // Null-terminate the entire buffer
3677+
3678+
// 2. Process the file from the in-memory buffer
3679+
char *current_pos = file_buffer;
3680+
char *buffer_end = file_buffer + file_size;
3681+
3682+
while (current_pos < buffer_end)
36343683
{
3635-
char line[1024];
3636-
char *keyword;
3637-
char *firstgid;
3638-
char *tilename;
3639-
int gid;
3640-
int layer = 0;
3684+
char line[1024];
3685+
char *line_end = strchr(current_pos, '\n');
3686+
long line_len;
36413687

3642-
if (fgets (line, 1024, fp) == NULL)
3643-
break;
3688+
if (line_end) {
3689+
line_len = line_end - current_pos;
3690+
} else {
3691+
line_len = buffer_end - current_pos;
3692+
}
36443693

3645-
keyword = strstr (line, "tileset firstgid=\"");
3646-
if (keyword != NULL)
3647-
{
3648-
firstgid = strstr (line, "firstgid=\"");
3649-
tilename = strstr (line, "name=\"");
3650-
if ((tilename != NULL) && (firstgid != NULL))
3651-
{
3652-
gid = atoi (firstgid + 10);
3653-
tilename = tilename + 6;
3654-
for (t = 0; t < 1024; t++)
3655-
if (line[t] == '"')
3656-
line[t] = 0;
3657-
s = 0;
3658-
for (t = gid; t < 256; t++)
3659-
{
3660-
sprintf (datavalues[t], " .byte <(%s+%d)\n", tilename, s);
3661-
s = s + 1;
3662-
if (doublewide == 1)
3663-
s = s + 1;
3664-
}
3665-
}
3666-
}
3694+
if (line_len >= sizeof(line)) {
3695+
prerror("line too long in map file '%s'", statement[2]);
3696+
}
3697+
3698+
memcpy(line, current_pos, line_len);
3699+
line[line_len] = '\0';
3700+
3701+
char *keyword;
3702+
char *firstgid;
3703+
char *tilename;
3704+
int gid;
3705+
int layer = 0;
3706+
3707+
keyword = strstr (line, "tileset firstgid=\"");
3708+
if (keyword != NULL)
3709+
{
3710+
firstgid = strstr (line, "firstgid=\"");
3711+
tilename = strstr (line, "name=\"");
3712+
if ((tilename != NULL) && (firstgid != NULL))
3713+
{
3714+
gid = atoi (firstgid + 10);
3715+
tilename = tilename + 6;
3716+
for (t = 0; t < 1024; t++)
3717+
if (line[t] == '"')
3718+
line[t] = 0;
3719+
s = 0;
3720+
for (t = gid; t < 256; t++)
3721+
{
3722+
sprintf (datavalues[t], " .byte <(%s+%d)\n", tilename, s);
3723+
s = s + 1;
3724+
if (doublewide == 1)
3725+
s = s + 1;
3726+
}
3727+
}
3728+
}
36673729

3668-
keyword = strstr (line, "tile gid=\"");
3669-
if (keyword != NULL)
3670-
{
3671-
gid = atoi (keyword + 10);
3672-
if (!thisdatabankset)
3673-
printf ("%s", datavalues[gid]);
3674-
else
3675-
gfxprintf ("%s", datavalues[gid]);
3676-
}
3730+
keyword = strstr (line, "tile gid=\"");
3731+
if (keyword != NULL)
3732+
{
3733+
gid = atoi (keyword + 10);
3734+
if (!thisdatabankset)
3735+
printf ("%s", datavalues[gid]);
3736+
else
3737+
gfxprintf ("%s", datavalues[gid]);
3738+
}
36773739

3678-
keyword = strstr (line, "<data encoding=\"");
3679-
if (keyword != NULL)
3680-
{
3681-
fclose (fp);
3682-
keyword = keyword + 15;
3683-
for (t = 0; t < 1024; t++)
3684-
if (line[t] == '"')
3685-
line[t] = 0;
3686-
prerror ("map file '%s' is %s encoded. XML is required", statement[2], keyword);
3687-
}
3688-
keyword = strstr (line, "<layer name=\"");
3689-
if (keyword != NULL)
3690-
{
3691-
layer = layer + 1;
3692-
if (layer > 1)
3693-
{
3694-
fclose (fp);
3695-
prerror ("map file '%s' contains multiple layers", statement[2]);
3696-
}
3697-
}
3740+
keyword = strstr (line, "<data encoding=\"");
3741+
if (keyword != NULL)
3742+
{
3743+
free(file_buffer);
3744+
keyword = keyword + 15;
3745+
for (t = 0; t < 1024; t++)
3746+
if (line[t] == '"')
3747+
line[t] = 0;
3748+
prerror ("map file '%s' is %s encoded. XML is required", statement[2], keyword);
3749+
}
3750+
keyword = strstr (line, "<layer name=\"");
3751+
if (keyword != NULL)
3752+
{
3753+
layer = layer + 1;
3754+
if (layer > 1)
3755+
{
3756+
free(file_buffer);
3757+
prerror ("map file '%s' contains multiple layers", statement[2]);
3758+
}
3759+
}
3760+
3761+
if (line_end) {
3762+
current_pos = line_end + 1;
3763+
} else {
3764+
break; // End of buffer
3765+
}
36983766
}
3699-
fclose (fp);
3767+
3768+
free(file_buffer);
37003769

37013770
if (!thisdatabankset)
37023771
printf ("skipmapdata%d\n", templabel);

0 commit comments

Comments
 (0)