Code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int parse_field(char *dst, size_t size, const char **src, char delim,
const char *replacement_text)
{
size_t i, replen = strlen(replacement_text);
int intext = 0;
for ( --size, i = 0; i < size; ++i )
{
if ( **src == '\0' )
{
if ( i == 0 )
{
return 0; /* nothing more to do */
}
break;
}
if ( isspace(**src) )
{
if ( intext )
{
break;
}
while ( isspace(**src) )
{
++*src;
}
}
else
{
intext = 1;
}
if ( **src != delim )
{
*dst++ = **src;
++*src;
}
else
{
while ( **src == delim )
{
++*src;
}
if ( i + replen < size )
{
memcpy(dst, replacement_text, replen);
dst += replen;
intext = 1;
}
else
{
size_t maxlen = size - i;
fprintf(stderr,
"[warning] parse buffer size too small (%d), need %d"
" : \"%.*s\" + \"%s\"\n",
(int)(size + 1), (int)(i + replen + 2),
(int)i, dst - i, replacement_text);
memcpy(dst, replacement_text, maxlen);
dst += replen;
break;
}
}
}
*dst = '\0';
return 1; /* continue parse engine */
}
void parse_user(const char *field)
{
for ( ;; )
{
size_t size = strcspn(field, ",");
printf(" [parse_user] field = \"%.*s\"\n", (int)size, field);
field += size;
if ( *field == '\0' )
{
break;
}
++field;
}
}
void parse_group(const char *field)
{
for ( ;; )
{
size_t size = strcspn(field, ",");
printf(" [parse_group] field = \"%.*s\"\n", (int)size, field);
field += size;
if ( *field == '\0' )
{
break;
}
++field;
}
}
void parse_other(const char *field)
{
printf(" [parse_other] field = \"%s\"\n", field);
}
void parse(const char *line, const char *user)
{
char field[32];
size_t state;
for ( state = 0; parse_field(field, sizeof field, &line, '&', user); ++state )
{
printf("[parse] field = \"%s\"\n", field);
switch ( state )
{
case 0: parse_user(field); break;
case 1: parse_group(field); break;
default: parse_other(field); break;
}
}
}
int main(void)
{
parse("user1,user2,&,user4 group1,group2,group3 string1 string2 string3", "user3");
return 0;
}
/* my output
[parse] field = "user1,user2,user3,user4"
[parse_user] field = "user1"
[parse_user] field = "user2"
[parse_user] field = "user3"
[parse_user] field = "user4"
[parse] field = "group1,group2,group3"
[parse_group] field = "group1"
[parse_group] field = "group2"
[parse_group] field = "group3"
[parse] field = "string1"
[parse_other] field = "string1"
[parse] field = "string2"
[parse_other] field = "string2"
[parse] field = "string3"
[parse_other] field = "string3"
*/