diff options
-rw-r--r-- | src/common/strlib.c | 99 | ||||
-rw-r--r-- | src/common/strlib.h | 15 |
2 files changed, 104 insertions, 10 deletions
diff --git a/src/common/strlib.c b/src/common/strlib.c index 5b53a29da..669833cb9 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -367,14 +367,13 @@ int strline(const char* str, size_t pos) ///////////////////////////////////////////////////////////////////// /// Parses a delim-separated string. -/// Starts parsing at startoff and fills the out_pos array with the start and -/// end positions in the string of the line and fields (that fit the array). -/// Returns the number of fields or -1 if an error occurs. +/// Starts parsing at startoff and fills the pos array with position pairs. +/// out_pos[0] and out_pos[1] are the start and end of line. +/// Other position pairs are the start and end of fields. +/// Returns the number of fields found or -1 if an error occurs. /// /// out_pos can be NULL. -/// Positions out_pos[0] and out_pos[1] are for the line start and end -/// positions. If a line terminator is found, the end position is placed there. -/// The next values of the array are the start and end positions of the fields. +/// If a line terminator is found, the end position is placed there. /// out_pos[2] and out_pos[3] for the first field, out_pos[4] and out_pos[5] /// for the seconds field and so on. /// Unfilled positions are set to -1. @@ -386,7 +385,7 @@ int strline(const char* str, size_t pos) /// @param out_pos Array of resulting positions /// @param npos Size of the pos array /// @param opt Options that determine the parsing behaviour -/// @return Number of fields in the string or -1 if an error occured +/// @return Number of fields found in the string or -1 if an error occured int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt) { int i; @@ -533,6 +532,92 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i return count; } +/// Splits a delim-separated string. +/// WARNING: this function modifies the input string +/// Starts splitting at startoff and fills the out_fields array. +/// out_fields[0] is the start of the next line. +/// Other entries are the start of fields (nul-teminated). +/// Returns the number of fields found or -1 if an error occurs. +/// +/// out_fields can be NULL. +/// Fields that don't fit in out_fields are not nul-terminated. +/// Extra entries in out_fields are filled with the end of line (empty string). +/// +/// @param str String to parse +/// @param len Length of the string +/// @param startoff Where to start parsing +/// @param delim Field delimiter +/// @param out_fields Array of resulting fields +/// @param nfields Size of the field array +/// @param opt Options that determine the parsing behaviour +/// @return Number of fields found in the string or -1 if an error occured +int sv_split(char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt) +{ + int pos[1024]; + int i; + int done; + char* eol; + int ret = sv_parse(str, len, startoff, delim, pos, ARRAYLENGTH(pos), opt); + + if( ret == -1 || out_fields == NULL || nfields <= 0 ) + return ret; // nothing to do + + // next line + eol = str + pos[1]; + if( eol[0] == '\0' ) + { + *out_fields = eol; + } + else if( (opt&SV_TERMINATE_LF) && eol[0] == '\n' ) + { + eol[0] = '\0'; + *out_fields = eol + 1; + } + else if( (opt&SV_TERMINATE_CRLF) && eol[0] == '\r' && eol[1] == '\n' ) + { + eol[0] = eol[1] = '\0'; + *out_fields = eol + 2; + } + else if( (opt&SV_TERMINATE_LF) && eol[0] == '\r' ) + { + eol[0] = '\0'; + *out_fields = eol + 1; + } + else + { + ShowError("sv_split: unknown line delimiter 0x02%x.\n", (unsigned char)eol[0]); + return -1;// error + } + ++out_fields; + --nfields; + + // fields + i = 2; + done = 0; + while( done < ret && nfields > 0 ) + { + if( i < ARRAYLENGTH(pos) ) + {// split field + *out_fields = str + pos[i]; + str[pos[i+1]] = '\0'; + // next field + i += 2; + ++done; + ++out_fields; + --nfields; + } + else + {// get more fields + sv_parse(str, len, pos[i-1] + 1, delim, pos, ARRAYLENGTH(pos), opt); + i = 2; + } + } + // remaining fields + for( i = 0; i < nfields; ++i ) + out_fields[i] = eol; + return ret; +} + /// Escapes src to out_dest according to the format of the C compiler. /// Returns the length of the escaped string. /// out_dest should be len*4+1 in size. diff --git a/src/common/strlib.h b/src/common/strlib.h index 004fe6375..dae7f8b98 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -65,11 +65,20 @@ typedef enum e_svopt #define SV_ESCAPE_C_SUPPORTED "abtnvfr\?\"'\\" /// Parses a delim-separated string. -/// Starts parsing at startoff and fills the pos array with the start and end -/// positions in the string of the line and fields (that fit the array). -/// Returns the number of fields or -1 if an error occurs. +/// Starts parsing at startoff and fills the pos array with position pairs. +/// out_pos[0] and out_pos[1] are the start and end of line. +/// Other position pairs are the start and end of fields. +/// Returns the number of fields found or -1 if an error occurs. int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt); +/// Splits a delim-separated string. +/// WARNING: this function modifies the input string +/// Starts splitting at startoff and fills the out_fields array. +/// out_fields[0] is the start of the next line. +/// Other entries are the start of fields (nul-teminated). +/// Returns the number of fields found or -1 if an error occurs. +int sv_split(char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt); + /// Escapes src to out_dest according to the format of the C compiler. /// Returns the length of the escaped string. /// out_dest should be len*4+1 in size. |