z_mirror/sdl-osu
git clone https://git.raiguard.me/z_mirror/sdl-osu
4bbec0e
trunk
1#include "beatmapreader.h" 2#include "osustring.h" 3#include "util.h" 4#include <ctype.h> 5#include <SDL3/SDL.h> 6#include <stdio.h> 7 8// Enumerates beatmap data from a stream. Calls keyValueCallback for key-value pairs and csvCallback for CSV rows. 9// Returns true if the read completed without errors. 10bool Osu_EnumerateBeatmapData (const char * data ,Osu_ReadBeatmapKeyValueCallback * keyValueCallback ,Osu_ReadBeatmapCSVCallback * csvCallback ,void * userdata ) { 11// TODO: Ask about what changes between versions of the file format. 12// if (!Osu_HasPrefix(data, "osu file format v14")) 13// { 14// OSU_LOG_TRACE("Invalid file version"); 15// return false; 16// } 17char * dataEnd = strchr (data ,0 ); 18char * cursor = strchr (data ,'\n' )+ 1 ; 19SDL_assert (cursor < dataEnd ); 20struct Osu_String * section = Osu_CreateString (); 21struct Osu_String * key = Osu_CreateString (); 22struct Osu_String * value = Osu_CreateString (); 23while (cursor < dataEnd ) { 24if (!* cursor ) { 25break ; 26 } 27char * lineEnd = strchr (cursor ,'\n' ); 28if (!lineEnd ) { 29break ; 30 } 31while (isspace (* cursor )&& cursor < dataEnd ) { 32cursor ++ ; 33 } 34if (lineEnd < cursor ) { 35continue ; 36 } 37while (isspace (* lineEnd )&& lineEnd > cursor ) { 38lineEnd -- ; 39 } 40if (cursor >=lineEnd ) { 41continue ; 42 } 43if (strncmp (cursor ,"//" ,2 )== 0 ) { 44cursor = lineEnd + 1 ; 45continue ; 46 } 47if (* cursor == '[' ) { 48if (* lineEnd != ']' ) { 49SDL_LogError (OSU_LOG_CATEGORY_BEATMAP_PARSER ,"Section end is '%c'" ,* lineEnd ); 50Osu_DestroyString (section ); 51Osu_DestroyString (key ); 52Osu_DestroyString (value ); 53return false; 54 } 55Osu_SetStringData (section ,cursor + 1 ,lineEnd - cursor - 1 ); 56OSU_LOG_TRACE (section -> buf ); 57cursor = lineEnd + 1 ; 58continue ; 59 } 60SDL_assert (cursor < lineEnd ); 61SDL_assert (cursor > data ); 62SDL_assert (lineEnd < dataEnd ); 63 64if (strcmp (section -> buf ,"Events" )== 0 || strcmp (section -> buf ,"HitObjects" )== 0 ) { 65char ** values = NULL ; 66size_t valuesLen = 0 ; 67char * sectionEnd = cursor ; 68while (sectionEnd <=lineEnd + 1 ) { 69if (* sectionEnd == ',' || sectionEnd == lineEnd + 1 ) { 70valuesLen ++ ; 71if (values ) { 72values = realloc (values ,sizeof (char * )* valuesLen );// TODO: Reallocating every single time is slow! 73 }else { 74values = malloc (sizeof (char * )* valuesLen ); 75 } 76values [valuesLen - 1 ]= malloc (sectionEnd - cursor + 1 ); 77strncpy (values [valuesLen - 1 ],cursor ,sectionEnd - cursor ); 78values [valuesLen - 1 ][sectionEnd - cursor ]= 0 ; 79cursor = sectionEnd + 1 ; 80 } 81sectionEnd ++ ; 82 } 83if (valuesLen > 0 ) { 84switch (csvCallback (section -> buf ,values ,valuesLen ,userdata )) { 85case SDL_ENUM_CONTINUE : 86break ; 87case SDL_ENUM_SUCCESS : 88Osu_DestroyString (section ); 89Osu_DestroyString (key ); 90Osu_DestroyString (value ); 91return true; 92case SDL_ENUM_FAILURE : 93Osu_DestroyString (section ); 94Osu_DestroyString (key ); 95Osu_DestroyString (value ); 96return false; 97 } 98for (size_t i = 0 ;i < valuesLen ;i ++ ) { 99free (values [i ]); 100 } 101free (values ); 102 } 103 }else { 104char * delim = memchr (cursor ,':' ,lineEnd - cursor + 1 ); 105if (!delim || delim >=lineEnd ) { 106OSU_LOG_TRACE ("Colon delimiter is beyond line end" ); 107cursor = lineEnd + 1 ; 108continue ; 109 } 110char * keyEnd = delim - 1 ; 111while (keyEnd > cursor && isspace (* keyEnd )) { 112keyEnd -- ; 113 } 114SDL_assert (keyEnd > cursor ); 115char * valueStart = delim + 1 ; 116while (valueStart < lineEnd && isspace (* valueStart )) { 117valueStart ++ ; 118 } 119SDL_assert (valueStart <=lineEnd ); 120Osu_SetStringData (key ,cursor ,keyEnd - cursor + 1 ); 121Osu_SetStringData (value ,valueStart ,lineEnd - valueStart + 1 ); 122 123if (keyValueCallback ) { 124switch (keyValueCallback (section -> buf ,key -> buf ,value -> buf ,userdata )) { 125case SDL_ENUM_CONTINUE : 126break ; 127case SDL_ENUM_SUCCESS : 128Osu_DestroyString (section ); 129Osu_DestroyString (key ); 130Osu_DestroyString (value ); 131return true; 132case SDL_ENUM_FAILURE : 133Osu_DestroyString (section ); 134Osu_DestroyString (key ); 135Osu_DestroyString (value ); 136return false; 137 } 138 } 139 } 140 141cursor = lineEnd + 1 ; 142 } 143 144Osu_DestroyString (section ); 145Osu_DestroyString (key ); 146Osu_DestroyString (value ); 147return true; 148}