Ejemplo n.º 1
0
static unsigned int getObject(char *start, char **first, char **last) {
    unsigned char state = ST_OBJECT_SEEK;
    char *dummy;
    unsigned char dummyType;
    unsigned int result;
    while(start[0] != '\0') {
        switch(state) {
            case ST_OBJECT_SEEK:
                if (start[0] == '{') {
                    state = ST_OBJECT_PROP_NAME;
                    *first = start;
                } else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_OBJECT;
                }
                break;
            case ST_OBJECT_PROP_SEEK:
                if (start[0] == '}') {
                    *last = start;
                    return PARSE_OK;
                } else if (start[0] == ',') {
                    state = ST_OBJECT_PROP_NAME;
                } else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_OBJECT;
                }
                break;
            case ST_OBJECT_PROP_NAME: 
                if (start[0] == '}') {
                    *last = start;
                    return PARSE_OK;
                } else if (!IS_WHITESPACE(start[0])) {
                    result = getString(start, &dummy , &start); 
                    if (result != PARSE_OK) {
                        return result;
                    } else {
                        state = ST_OBJECT_PROP_PARSE;
                    }
                }
                break;
            case ST_OBJECT_PROP_PARSE:
                if (start[0] == ':') {
                    state = ST_OBJECT_PROP_VAL;
                } else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_OBJECT;
                }
                break;
            case ST_OBJECT_PROP_VAL:
                result = getValue(start, &dummy , &start, &dummyType);
                if (result != PARSE_OK) {
                    return result;
                } else {
                    state = ST_OBJECT_PROP_SEEK;
                }
                break;
        }
                
        ++start;
    }

    return ERR_PARSE_OBJECT;
}
Ejemplo n.º 2
0
unsigned int readNextName(char *start, char **first, char **last, unsigned int *hash) {
    unsigned char state = ST_OBJECT_SEEK;
    while(start[0] != '\0') {
        switch(state) {
            case ST_OBJECT_SEEK:
                if (start[0] == '{') {
                    state = ST_OBJECT_PROP_NAME;
                } else if (!IS_WHITESPACE(start[0])) {
                    state = ST_OBJECT_PROP_SEEK;
                } 
                break;
            case ST_OBJECT_PROP_SEEK:
                if (start[0] == ',') {
                    state = ST_OBJECT_PROP_NAME;
                } else if (start[0] == '}') {
                    *first = start;
                    *last = start;
                    return PARSE_END;
                } else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_OBJECT;
                }
                break;
            case ST_OBJECT_PROP_NAME: 
                if (!IS_WHITESPACE(start[0])) {
                    return getStringAndHash(start, first, last, hash);
                }
                break;
        }

        ++start;
    }

    return ERR_PARSE_OBJECT;
}
Ejemplo n.º 3
0
void 
_ppt::_parse_command_input(
	const std::string &input,
	std::vector<arg> &arguments
	)
{
	TRACE_EVENT("+_ppt::_parse_command_input", TRACE_TYPE_VERBOSE);

	size_t i = 0;
	std::string curr_input;

	for(; i < input.size(); ++i) {

		while(i < input.size()
				&& IS_WHITESPACE(input.at(i))) {
			++i;
		}

		while(i < input.size()
				&& !IS_WHITESPACE(input.at(i))) {
			curr_input += input.at(i);
			++i;
		}
		arguments.push_back(arg(curr_input, ARG_TYPE_STRING));
		curr_input.clear();
	}

	TRACE_EVENT("+_ppt::_parse_command_input", TRACE_TYPE_VERBOSE);
}
Ejemplo n.º 4
0
palo_err string_get_word_or_whitespace_a(char **to, const char *from, size_t *index) {
	size_t idx, last_idx;

	assert(to != NULL);
	assert(from != NULL);
	assert(index != NULL);

	if (IS_WHITESPACE(from[*index])) {
		*to = strdupf("%c", from[*index]);
		if (*to == NULL) {
				return PALO_ERR_NO_MEM;
		}
		++(*index);
		return PALO_SUCCESS;
	}

	/* skip data */
	for (idx = *index; !IS_WHITESPACE(from[idx]) && from[idx] != L'\0'; idx++);
	last_idx = idx;

	*to = (char*)malloc((last_idx - *index + 1) * sizeof(char));
	if (*to == NULL) {
			return PALO_ERR_NO_MEM;
	}
	memcpy(*to, from + *index, (last_idx - *index)*sizeof(char));
	(*to)[last_idx-*index] = '\0';

	*index = idx;

	return PALO_SUCCESS;
}
Ejemplo n.º 5
0
static char *parse_key(const char **key, char *p, nx_json_unicode_encoder encoder) {
    // on '}' return with *p=='}'
    char c;
    while ((c = *p++)) {
        if (c == '"') {
            *key = unescape_string(p, &p, encoder);
            if (!*key)
                return 0;       // propagate error
            while (*p && IS_WHITESPACE(*p))
                p++;
            if (*p == ':')
                return p + 1;
            NX_JSON_REPORT_ERROR("unexpected chars", p);
            return 0;
        }
        else if (IS_WHITESPACE(c) || c == ',') {
            // continue
        }
        else if (c == '}') {
            return p - 1;
        }
        else if (c == '/') {
            if (*p == '/') {    // line comment
                char *ps = p - 1;
                p = strchr(p + 1, '\n');
                if (!p) {
                    NX_JSON_REPORT_ERROR("endless comment", ps);
                    return 0;   // error
                }
                p++;
            }
            else if (*p == '*') {       // block comment
                p = skip_block_comment(p + 1);
                if (!p)
                    return 0;
            }
            else {
                NX_JSON_REPORT_ERROR("unexpected chars", p - 1);
                return 0;       // error
            }
        }
        else {
            NX_JSON_REPORT_ERROR("unexpected chars", p - 1);
            return 0;           // error
        }
    }
    NX_JSON_REPORT_ERROR("unexpected chars", p - 1);
    return 0;                   // error
}
Ejemplo n.º 6
0
/*
//  Trouble! In files, import and export specifiers may or may not have a trailing comma
//  so we look ahead to Token.next and see if there is a comma next (after whitespace)
//  and if there is then we don't set this flag else we do
//  this also affects us using
//      IMPORT x, (PREFIX), y, (PREFIX), x
*/
static bool DoWeNeedToSkipASeparator( bool CheckDirectives )
{
    char *parse;

    if( (NULL == (parse = Token.next)) || ('\0' == *parse) )
        return( false );

    while( ('\0' != *parse) && IS_WHITESPACE( parse ) )
        parse++;

    if( '\0' == *parse )
        return( false );

    if( ',' == *parse )
        return( false );

    /*
    //  skip cr-lf
    */
    if( ('\n' == *parse) || ('\r' == *parse) )
        parse++;
    if( ('\n' == *parse) || ('\r' == *parse) )
        parse++;

    /*
    //  always skip to the next token if the next available token is not a comma
    //  this will allow individual tokens without commas which isn't a big deal
    */
    if( ('\0' != *parse) && (',' != *parse) ) {
        /*
        //  If the next token is __not__ a comma then we need to check that it is not a directive
        //  before allowing the skip!
        */
        if( CheckDirectives ) {
            size_t      len = 0;
            char        *t;

            for( t = parse; !IS_WHITESPACE(t); ++t ) {
                len++;
            }

            if( MatchOne( Directives, SEP_NO, parse, len ) ) {
                return( false );
            }
        }
        return( true );
    }
    return( false );
}
Ejemplo n.º 7
0
long webc_scan_string (WEBC_CHAR *dest, WEBC_CHAR *src, long maxLen)
{
	int inparen = 0;
	long len = 0;

	// Get the next token separated by whitespace
	// ignore whitespace terminator if surround by () (for rgb( rr, gg, bb))
	while (*src && (len < (maxLen-1)) )// && (!inparen && !IS_WHITESPACE(*src)))
	{
		if (!inparen && IS_WHITESPACE(*src))
			break;
		WEBC_CHAR c = *src;
		if (c == parens[0])
			inparen = 1;
		*dest = *src;
		dest++;
		src++;
		len++;
		if (c == parens[1] && inparen)
			break;
	}
	*dest = 0;

	return (len);
}
Ejemplo n.º 8
0
unsigned int readNextArrayValue(char *start, char **first, char **last, unsigned char *type) {
    unsigned char state = ST_OBJECT_PROP_PARSE;
    if (start[0] == '[') {
        state = ST_OBJECT_PROP_VAL;
    } 
    ++start;
    while(start[0] != '\0') {
        switch(state) {
            case ST_OBJECT_PROP_PARSE:
                if (start[0] == ',') {
                    state = ST_OBJECT_PROP_VAL;
                } else if (start[0] == ']') {
                    *first = start;
                    *last = start;
                    return PARSE_END;    
                } else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_OBJECT;
                }
                break;
            case ST_OBJECT_PROP_VAL:
                return getValue(start, first, last, type);
                break;
        }
                
        ++start;
    }

    return ERR_PARSE_OBJECT;
}
Ejemplo n.º 9
0
int fast_atoi(const std::string & src)
{
    if (src.empty())
        return 0;
    const char * p = &src[0];
    const char * end = p + src.size();
    int value = 0;
    int sign = 1;

    while (IS_WHITESPACE(*p) || *p == '0') {
        INCREMENT_PTR();
    }

    switch (*p) {
        case '-':
            sign = -1;
            INCREMENT_PTR();
            break;
        case '+':
            INCREMENT_PTR();
            break;
        default:
            break;
    }

    while (IS_DIGIT(*p)) {
        value = value * 10 + (*p - '0');
        INCREMENT_PTR();
    }

parse_end:
    return value * sign;
}
Ejemplo n.º 10
0
void TokenReader::skipWhitespace() {
    int c;
    if (pbc != -1) {
	c = pbc;
	pbc = -1;
    } else {
	NEXTC;
    }

again:
    while (IS_WHITESPACE(c)) {
        NEXTC;
    }

    if (c == '#') {
	do {
	    NEXTC;
	} while (c != EOF && c != '\n');
	if (c != EOF)
	    goto again;
    }

    pbc = c;

    if (c == -1) {
	eof = true;
    }
}
Ejemplo n.º 11
0
static int flag_to_flag(RCore *core, const char *glob) {
	r_return_val_if_fail (glob, 0);
	glob = r_str_trim_ro (glob);
	struct flag_to_flag_t u = { .next = UT64_MAX, .offset = core->offset };
	r_flag_foreach_glob (core->flags, glob, flag_to_flag_foreach, &u);
	if (u.next != UT64_MAX && u.next > core->offset) {
		return u.next - core->offset;
	}
	return 0;
}

static void cmd_flag_tags (RCore *core, const char *input) {
	char mode = input[1];
	for (; *input && !IS_WHITESPACE (*input); input++) {}
	char *inp = strdup (input);
	char *arg = r_str_trim (inp);
	if (!*arg && !mode) {
		const char *tag;
		RListIter *iter;
		RList *list = r_flag_tags_list (core->flags);
		r_list_foreach (list, iter, tag) {
			r_cons_printf ("%s\n", tag);
		}
		r_list_free (list);
		free (inp);
		return;
	}
Ejemplo n.º 12
0
static unsigned int getString(char *start, char **first, char **last) {
    unsigned char state = ST_STRING_SEEK;
    char delimiter = '\0';
    while(start[0] != '\0') {
        switch (state) {
            case ST_STRING_SEEK:
                if (start[0] == '"' || start[0] == '\'') {
                    state = ST_STRING_PARSE;
                    delimiter = start[0];
                    *first = start + 1;
                }
                else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_STRING;
                }
                break;
            case ST_STRING_PARSE:
                if (start[0] == delimiter) {
                    *last = start;
                    return PARSE_OK;
                } else if (start[0] == '\\') {
                    state = ST_STRING_ESC;  
                }
                break;
            case ST_STRING_ESC:
                state = ST_STRING_PARSE;
                break;
        }

        ++ start;
    }

    return ERR_PARSE_STRING;
}
Ejemplo n.º 13
0
/*
 * Append text to the text buffer.
 *
 * For the first chunk of text, all whitespace characters before the
 * first non-whitespace character are stripped.  This saves time
 * stripping on the Python side later.
 */
static int
text_append(IterParser *self, const XML_Char *data, Py_ssize_t len)
{
    Py_ssize_t new_size;

    if (len == 0) {
        return 0;
    }

    /* If this is the first chunk, handle whitespace */
    if (self->text_size == 0) {
        while (len && IS_WHITESPACE(*data)) {
            ++data;
            --len;
        }
    }

    /* Grow text buffer if necessary */
    new_size = self->text_size + len;
    if (text_realloc(self, new_size + 1)) {
        return -1;
    }

    memcpy(self->text + self->text_size,
           data,
           (size_t)len * sizeof(XML_Char));

    self->text_size = new_size;
    self->text[self->text_size] = (XML_Char)0x0;

    return 0;
}
Ejemplo n.º 14
0
static int image_read_header(FILE *fh, u16 *w, u16 *h, u32 *black, u32 *white)
{
    u8 buf[48];
    int err = 0;
    u16 *w_h[] = {w, h};
    *white = 0xffffff;
    *black = 0x000000;

    *w = 0;
    *h = 0;
    int ret = fread(buf,3, 1, fh);
    if (ret != 1 || buf[0] != 'P' || buf[1] != '4') {
        err = 1;
    }

    if (fgets((char *)buf, sizeof(buf), fh) == NULL) {
        printf("DEBUG: image_read_header: Error: failed to read comment or dimensions\n");
        return 0;
    }
    if (buf[0] == '#') {
        if (fgets((char *)buf, sizeof(buf), fh) == NULL) {
            printf("DEBUG: image_read_header: Error: failed to read dimensions\n");
            return 0;
        }
    }
    u8 *ptr = buf;
    for (int i = 0; i < 2; i++) {
        u16 *v = w_h[i];
        while(!err) {
            if (ptr == buf + sizeof(buf) || (! IS_WHITESPACE(*ptr) && (*ptr < '0' || *ptr > '9'))) {
                err = 1;
                break;
            }
            if (IS_WHITESPACE(*ptr)) {
                ptr++;
                break;
            }
            *v = *v * 10 + *ptr - '0';
            ptr++;
        }
    }
    if (err) {
        printf("DEBUG: image_read_header: Error: %d, h:%d w:%d\n", err, *h, *w);
        return 0;
    }
    return 1;
}
Ejemplo n.º 15
0
static unsigned int getArray(char *start, char** first, char **last) {
    unsigned char state = ST_ARRAY_SEEK;
    char *dummy;
    unsigned char dummyType;
    unsigned int result;
    while(start[0] != '\0') {
        switch(state) {
            case ST_ARRAY_SEEK:
                if (start[0] == '[') {
                    state = ST_ARRAY_VAL_PARSE;
                    *first = start;
                } else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_ARRAY;
                }
                break;
            case ST_ARRAY_VAL_SEEK:
                if (start[0] == ']') {
                    *last = start;
                    return PARSE_OK;
                }
                else if (start[0] == ',') {
                    state = ST_ARRAY_VAL_PARSE;
                } else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_ARRAY;
                }
                break;
            case ST_ARRAY_VAL_PARSE: 
                if (start[0] == ']') {
                    *last = start;
                    return PARSE_OK;
                } else if (!IS_WHITESPACE(start[0])) {
                    result = getValue(start, &dummy , &start, &dummyType); 
                    if (result != PARSE_OK) {
                        return result;
                    } else {
                        state = ST_ARRAY_VAL_SEEK;
                    }
                }
                break;
        }

        ++start;
    }
    
    return ERR_PARSE_ARRAY;
}
Ejemplo n.º 16
0
R_API void r_cons_chop () {
	while (I.buffer_len>0) {
		char ch = I.buffer[I.buffer_len-1];
		if (ch != '\n' && !IS_WHITESPACE (ch))
			break;
		I.buffer_len--;
	}
}
Ejemplo n.º 17
0
WEBC_CHAR * webc_scan_whitespace (WEBC_CHAR *src)
{
	while (IS_WHITESPACE(*src))
	{
		src++;
	}

	return (src);
}
Ejemplo n.º 18
0
// reads until first non-whitespace character
void MD5Model::skipWhitespace(std::ifstream &fin) {
	char c = '\0';
	while (!fin.eof()) {
		fin.get(c);

		if (!IS_WHITESPACE(c)) {
			fin.putback(c);
			break;
		}
	}
}
Ejemplo n.º 19
0
bool SetCurrentPrefix(const char * pszPrefix, size_t nLen)
{
    const char *    pStart = pszPrefix;
    char *          pFix;
    unsigned        nIntLen = nLen;
    char            *newbuff = NULL;

    /*
    //  Always delete
    */
    if( CmdFile->symprefix ) {
        _LnkFree( CmdFile->symprefix );
        CmdFile->symprefix = NULL;
    }

    if( (NULL == pStart) || (nLen == 0) ) {
        return TRUE;
    }

    pStart++;   /* skip opening parentheses */
    nIntLen--;  /* and record that */

    while( (0 != *pStart) && IS_WHITESPACE(pStart) )
        pStart++, nIntLen--;

    if( (0 == *pStart) || (0 == nLen) )
        return FALSE;

    /* convert to C string */
    _LnkAlloc( newbuff, nIntLen + 1 );
    memcpy( newbuff, pStart, nIntLen - 1 );
    newbuff[nIntLen-1] = '\0';
    CmdFile->symprefix = newbuff;

    pFix = newbuff;
    while( (0 != *pFix) && !IS_WHITESPACE(pFix) )
        pFix++;
    *pFix = '\0';

    return( 0 != strlen( newbuff ));
}
Ejemplo n.º 20
0
char *rtrim ( char *dst, const char *src )
{
	int pos = strlen ( src ), len = pos, i;

	while ( IS_WHITESPACE ( src[--pos] ) );

	for ( i = 0; i <= pos; i++ )
		dst[i] = src[i];

	dst[i] = '\0';
	return dst;
}
Ejemplo n.º 21
0
Archivo: cmds.c Proyecto: hankem/jed
/* does not leave current line */
unsigned char *jed_skip_whitespace (void)
{
   unsigned char *p, *pmax;

   p = CLine->data + Point;
   pmax = jed_eol_position (CLine);

   while ((p < pmax) && IS_WHITESPACE(p))
     p = jed_multibyte_chars_forward (p, pmax, 1, NULL, 0);

   jed_position_point (p);
   return p;
}
Ejemplo n.º 22
0
static unsigned int getValue(char *start, char **first, char **last, unsigned char *type) {
    *type = JSON_OBJECT;
    while(start[0] != '\0') {   
        if (start[0] == '"' || start[0] == '\'') {
            *type = JSON_STRING;
            return getString(start, first, last);
        } else if ((start[0] >= '0' && start[0] <= '9') || start[0] == '-') {
            return getNumber(start, first, last, type);
        } else if (start[0] == 'f') {
            if (strncmp(start, "false", 5) == 0) {
                *first = start;
                *last = start + 4;
                *type = JSON_BOOL;
                return PARSE_OK;
            } else {
                return ERR_PARSE_STRING;
            }
        } else if (start[0] == 't') {
            if (strncmp(start, "true", 4) == 0) {
                *first = start;
                *last = start + 3;
                *type = JSON_BOOL;
                return PARSE_OK;
            } else {
                return ERR_PARSE_STRING;
            }
        } else if (start[0] == 'N') {
            if (strncmp(start, "NaN", 3) == 0) {
                *first = start;
                *last = start + 2;
                *type = JSON_NIL;
                return PARSE_OK;
            } else {
                return ERR_PARSE_STRING;
            }
        } else if (start[0] == '{') {
            *type = JSON_OBJECT;
            unsigned int result = getObject(start, first, last);
            return result; 
        } else if (start[0] == '[') {
            *type = JSON_ARRAY;
            return getArray(start, first, last);
        } else if (!IS_WHITESPACE(start[0])) {
            return ERR_PARSE_STRING;
        } 

        ++start;
    }

    return ERR_PARSE_VALUE;
}
Ejemplo n.º 23
0
char *ltrim ( char *dst, const char *src )
{
	int pos = -1, len = strlen ( src ), i;

	while ( IS_WHITESPACE ( src[++pos] ) );

	int end = len - pos;

	for ( i = 0; i < end; i++ )
		dst[i] = src[i + pos];

	dst[i] = '\0';
	return dst;
}
Ejemplo n.º 24
0
int rsa_sprintf_nows(char *str, char *fmt, ...)
{
	va_list ap;
	int ret;

	va_start(ap, fmt);
	ret = vsprintf(str, fmt, ap);
	va_end(ap);

	for ( ; *str; str++) {
		if (IS_WHITESPACE(*str))
			*str = '_';
	}
	return ret;
}
Ejemplo n.º 25
0
static unsigned int getNumber(char *start, char **first, char **last, unsigned char *type) {
    unsigned char state = ST_NUMBER_SEEK;
    *type = JSON_INT;
    while(start[0] != '\0') {
        switch(state) {
            case ST_NUMBER_SEEK:
                if ((start[0] >= '0' && start[0] <= '9') || start[0] == '-') {
                    state = ST_NUMBER_INT;
                    *first = start;
                } else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_NUMBER;
                }
                break;
            case ST_NUMBER_INT:
                if (start[0] == '.') {
                    state = ST_NUMBER_FRA;
                    *type = JSON_DOUBLE;
                } else if (start[0] < '0' || start[0] > '9') {
                    *last = start - 1;
                    return PARSE_OK;
                }
                break;
            case ST_NUMBER_FRA:
                if (start[0] == 'e' || start[0] == 'E') {
                    state = ST_NUMBER_EXP;
                    if (start[1] == '+' || start[1] == '-') {
                        ++ start;
                    }
                } else if (start[0] < '0' || start[0] > '9') {
                    *last = start - 1;
                    return PARSE_OK;
                }
                break;
            case ST_NUMBER_EXP:
                if (start[0] < '0' || start[0] > '9') {
                    *last = start - 1;
                    return PARSE_OK;
                }
                break;
        }

        ++start;
    }

    return ERR_PARSE_NUMBER;
}
Ejemplo n.º 26
0
Archivo: cmds.c Proyecto: hankem/jed
unsigned char *jed_bskip_whitespace (void)
{
   unsigned char *p, *pmin;

   pmin = CLine->data;
   p = CLine->data + Point;

   while (p > pmin)
     {
	unsigned char *p1;
	p1 = jed_multibyte_chars_backward (pmin, p, 1, NULL, 0);
	if (0 == IS_WHITESPACE(p1))
	  break;
	p = p1;
     }
   jed_position_point (p);
   return p;
}
Ejemplo n.º 27
0
Archivo: cmds.c Proyecto: hankem/jed
int jed_trim_whitespace ()
{
   int n;
   unsigned char *p;

   /* CHECK_READ_ONLY */

   p = CLine->data + Point;
   if ((0 == eolp ()) && (0 == IS_WHITESPACE(p)))
     return 0;

   (void) jed_skip_whitespace ();
   n = Point;

   (void) jed_bskip_whitespace ();
   if (-1 == jed_del_nbytes (n - Point))
     return -1;

   return 1;
}
Ejemplo n.º 28
0
int sub_buffernum(int* status, FILE* stream, char* buf, int limit) {
    int digits;
    digits  = 0;
    *status = 0;
        
    while(digits < limit) {
        buf[digits] = fgetc(stream);
        
        if ((buf[digits] == ')') || (buf[digits] == ']')) {
            *status = 255;
            break;
        }
        if (IS_WHITESPACE(buf[digits])) {
            break;
        }
        
        digits++;
    }
    
    return digits;
}
Ejemplo n.º 29
0
unsigned int readNextString(char *start, char **first, char **last, unsigned int *hash) {
    unsigned char state = ST_OBJECT_PROP_PARSE;
    ++start;
    while(start[0] != '\0') {
        switch(state) {
            case ST_OBJECT_PROP_PARSE:
                if (start[0] == ':') {
                    state = ST_OBJECT_PROP_VAL;
                } else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_OBJECT;
                }
                break;
            case ST_OBJECT_PROP_VAL:
                return getStringAndHash(start, first, last, hash);
        }
                
        ++start;
    }

    return ERR_PARSE_OBJECT;
}
Ejemplo n.º 30
0
static unsigned int getStringAndHash(char *start, char **first, char **last, unsigned int *hash) {
    unsigned char state = ST_STRING_SEEK;
    char delimiter = '\0';
    unsigned int currentHash = 5381;
    while(start[0] != '\0') {
        switch (state) {
            case ST_STRING_SEEK:
                if (start[0] == '"' || start[0] == '\'') {
                    state = ST_STRING_PARSE;
                    delimiter = start[0];
                    *first = start + 1;
                }
                else if (!IS_WHITESPACE(start[0])) {
                    return ERR_PARSE_STRING;
                }
                break;
            case ST_STRING_PARSE:
                if (start[0] == delimiter) {
                    *last = start;
                    *hash = currentHash;
                    return PARSE_OK;
                } else if (start[0] == '\\') {
                    state = ST_STRING_ESC;  
                }

                currentHash = ((currentHash << 5) + currentHash) + (*start);
                break;
            case ST_STRING_ESC:
                state = ST_STRING_PARSE;
                currentHash = ((currentHash << 5) + currentHash) + (*start);
                break;
        }

        ++ start;
    }

    return ERR_PARSE_STRING;
}