cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

parsehelper.c (5318B)


      1/* See COPYING.txt for the full license governing this code. */
      2/**
      3 * \file parsehelper.c
      4 *
      5 * Source file with some helper functions for parsing strings.
      6 */
      7
      8#include <SDL_test.h>
      9#include "SDL_visualtest_harness_argparser.h"
     10
     11/* this function uses a DFA to count the number of tokens in an agruments string.
     12   state 0 is taken to be the start and end state. State 1 handles a double quoted
     13   argument and state 2 handles unquoted arguments. */
     14static int
     15CountTokens(char* args)
     16{
     17    int index, num_tokens;
     18    int state; /* current state of the DFA */
     19
     20    if(!args)
     21    	return -1;
     22
     23    index = 0;
     24    state = 0;
     25    num_tokens = 0;
     26    while(args[index])
     27    {
     28        char ch = args[index];
     29        switch(state)
     30        {
     31            case 0:
     32            if(ch == '\"')
     33            {
     34                state = 1;
     35                num_tokens++;
     36            }
     37            else if(!SDL_isspace(ch))
     38            {
     39                state = 2;
     40                num_tokens++;
     41            }
     42            break;
     43
     44            case 1:
     45            if(ch == '\"')
     46            {
     47                state = 0;
     48            }
     49            break;
     50
     51            case 2:
     52            if(SDL_isspace(ch))
     53            {
     54                state = 0;
     55            }
     56            break;
     57        }
     58        index++;
     59    }
     60    return num_tokens;
     61}
     62
     63/* - size of tokens is num_tokens + 1
     64- uses the same DFA used in CountTokens() to split args into an array of strings */
     65static int
     66TokenizeHelper(char* str, char** tokens, int num_tokens, int max_token_len)
     67{
     68    int index, state, done, st_index, token_index;
     69
     70    if(!str)
     71    {
     72        SDLTest_LogError("str argument cannot be NULL");
     73        return 0;
     74    }
     75    if(!tokens)
     76    {
     77        SDLTest_LogError("tokens argument cannot be NULL");
     78        return 0;
     79    }
     80    if(num_tokens <= 0)
     81    {
     82        SDLTest_LogError("num_tokens argument must be positive");
     83        return 0;
     84    }
     85    if(max_token_len <= 0)
     86    {
     87        SDLTest_LogError("max_token_len argument must be positive");
     88        return 0;
     89    }
     90
     91    /* allocate memory for the tokens */
     92    tokens[num_tokens] = NULL;
     93    for(index = 0; index < num_tokens; index++)
     94    {
     95        tokens[index] = (char*)SDL_malloc(max_token_len);
     96        if(!tokens[index])
     97        {
     98            int i;
     99            SDLTest_LogError("malloc() failed.");
    100            for(i = 0; i < index; i++)
    101                SDL_free(tokens[i]);
    102            return 0;
    103        }
    104        tokens[index][0] = '\0';
    105    }
    106
    107    /* copy the tokens into the array */
    108    st_index = 0;
    109    index = 0;
    110    token_index = 0;
    111    state = 0;
    112    done = 0;
    113    while(!done)
    114    {
    115        char ch = str[index];
    116        switch(state)
    117        {
    118            case 0:
    119            if(ch == '\"')
    120            {
    121                state = 1;
    122                st_index = index + 1;
    123            }
    124            else if(!ch)
    125                done = 1;
    126            else if(ch && !SDL_isspace(ch))
    127            {
    128                state = 2;
    129                st_index = index;
    130            }
    131            break;
    132
    133            case 1:
    134            if(ch == '\"')
    135            {
    136                int i;
    137                state = 0;
    138                for(i = st_index; i < index; i++)
    139                {
    140                    tokens[token_index][i - st_index] = str[i];
    141                }
    142                tokens[token_index][i - st_index] = '\0';
    143                token_index++;
    144            }
    145            else if(!ch)
    146            {
    147                SDLTest_LogError("Parsing Error!");
    148                done = 1;
    149            }
    150            break;
    151
    152            case 2:
    153            if(!ch)
    154                done = 1;
    155            if(SDL_isspace(ch) || !ch)
    156            {
    157                int i;
    158                state = 0;
    159                for(i = st_index; i < index; i++)
    160                {
    161                    tokens[token_index][i - st_index] = str[i];
    162                }
    163                tokens[token_index][i - st_index] = '\0';
    164                token_index++;
    165            }
    166            break;
    167        }
    168        index++;
    169    }
    170    return 1;
    171}
    172
    173char**
    174SDLVisualTest_Tokenize(char* str, int max_token_len)
    175{
    176    int num_tokens;
    177    char** tokens;
    178
    179    if(!str)
    180    {
    181        SDLTest_LogError("str argument cannot be NULL");
    182        return NULL;
    183    }
    184    if(max_token_len <= 0)
    185    {
    186        SDLTest_LogError("max_token_len argument must be positive");
    187        return NULL;
    188    }
    189
    190    num_tokens = CountTokens(str);
    191    if(num_tokens == 0)
    192        return NULL;
    193
    194    tokens = (char**)SDL_malloc(sizeof(char*) * (num_tokens + 1));
    195    if(!TokenizeHelper(str, tokens, num_tokens, max_token_len))
    196    {
    197        SDLTest_LogError("TokenizeHelper() failed");
    198        SDL_free(tokens);
    199        return NULL;
    200    }
    201    return tokens;
    202}
    203
    204char**
    205SDLVisualTest_ParseArgsToArgv(char* args)
    206{
    207    char** argv;
    208    int num_tokens;
    209
    210    num_tokens = CountTokens(args);
    211    if(num_tokens == 0)
    212        return NULL;
    213
    214    /* allocate space for arguments */
    215    argv = (char**)SDL_malloc((num_tokens + 2) * sizeof(char*));
    216    if(!argv)
    217    {
    218        SDLTest_LogError("malloc() failed.");
    219        return NULL;
    220    }
    221
    222    /* tokenize */
    223    if(!TokenizeHelper(args, argv + 1, num_tokens, MAX_SUT_ARGS_LEN))
    224    {
    225        SDLTest_LogError("TokenizeHelper() failed");
    226        SDL_free(argv);
    227        return NULL;
    228    }
    229    argv[0] = NULL;
    230    return argv;
    231}