inline static grn_cell * get_op(grn_query *q, grn_operator op, int weight) { char *start, *end = q->cur; int mode, option; switch (*end) { case 'S' : mode = GRN_OP_SIMILAR; start = ++end; option = grn_atoi(start, q->str_end, (const char **)&end); if (start == end) { option = DEFAULT_SIMILARITY_THRESHOLD; } q->cur = end; break; case 'N' : mode = GRN_OP_NEAR; start = ++end; option = grn_atoi(start, q->str_end, (const char **)&end); if (start == end) { option = DEFAULT_MAX_INTERVAL; } q->cur = end; break; case 'n' : mode = GRN_OP_NEAR2; start = ++end; option = grn_atoi(start, q->str_end, (const char **)&end); if (start == end) { option = DEFAULT_MAX_INTERVAL; } q->cur = end; break; case 'T' : mode = GRN_OP_TERM_EXTRACT; start = ++end; option = grn_atoi(start, q->str_end, (const char **)&end); if (start == end) { option = DEFAULT_TERM_EXTRACT_POLICY; } q->cur = end; break; case 'X' : /* force exact mode */ op = GRN_OP_AND; mode = GRN_OP_EXACT; option = 0; start = ++end; q->cur = end; break; default : return NIL; } return op_new(q, op, weight, mode, option); }
inline static grn_cell * get_token(grn_ctx *ctx, grn_query *q) { grn_cell *token = NIL; grn_operator op = q->default_op; { int weight = DEFAULT_WEIGHT, prefixp = 0, mode = -1, option = 0; skip_space(ctx, q); if (q->cur_expr >= q->max_exprs || q->cur_cell >= q->max_cells || q->cur >= q->str_end) { return NIL; } switch (*q->cur) { case '\0' : return NIL; case GRN_QUERY_PARENR : q->cur++; return NIL; case GRN_QUERY_QUOTEL : q->cur++; if ((token = get_phrase(ctx, q)) == NULL) { return NIL; } break; case GRN_QUERY_PREFIX : q->cur++; token = get_op(q, op, weight); break; case GRN_QUERY_AND : q->cur++; token = op_new(q, GRN_OP_AND, weight, mode, option); break; case GRN_QUERY_BUT : q->cur++; token = op_new(q, GRN_OP_BUT, weight, mode, option); break; case GRN_QUERY_ADJ_INC : q->cur++; if (weight < 127) { weight++; } token = op_new(q, GRN_OP_ADJUST, weight, mode, option); break; case GRN_QUERY_ADJ_DEC : q->cur++; if (weight > -128) { weight--; } token = op_new(q, GRN_OP_ADJUST, weight, mode, option); break; case GRN_QUERY_ADJ_NEG : q->cur++; token = op_new(q, GRN_OP_ADJUST, -1, mode, option); break; case GRN_QUERY_PARENL : q->cur++; token = get_expr(ctx, q); break; default : if ((token = get_word(ctx, q, &prefixp)) && token->u.b.value[0] == 'O' && token->u.b.value[1] == 'R' && token->u.b.size == 2) { cell_del(q); q->cur_expr--; token = op_new(q, GRN_OP_OR, weight, mode, option); } break; } } return cons(q, token, NIL); }
int parse_json(uint16_t json_sz) { int ret = SUCCESS; char *cursor = json; char *op = NULL; char *line_start = NULL, *line_end = NULL, *delim = NULL; uint16_t remaining = json_sz; uint16_t line_remaining = 0; uint16_t consumed = 0; // There's nothing to do; just return. if (0 == json_sz) { #ifdef DEBUG fprintf(stderr, "[D] parse_json | json_sz = 0x%04x; nothing to do\n", json_sz); #endif goto bail; } // For each INSN (1 per line)... while (NULL != (line_start = strnchr(cursor, '\n', (uint32_t)remaining))) { #ifdef DEBUG fprintf(stderr, "[D] parse_json | top of loop; line_start = '%s'\n", line_start); #endif // Consume the newline. line_start += 1; remaining -= 1; // If there's nothing left, we've parse it all. if (0 == remaining) { #ifdef DEBUG fprintf(stderr, "[D] parse_json | consumed all JSON\n", remaining); #endif goto bail; } // Find next newline (so we have bounds to this line). if (NULL == (line_end = strnchr(line_start, '\n', (uint32_t)remaining))) { #ifdef DEBUG fprintf(stderr, "[E] parse_json | could not find next line ending; line_start is: '%s'\n", line_start); #endif ret = ERRNO_MALFORMED_JSON; goto bail; } line_remaining = line_end - line_start; cursor = line_start; #ifdef DEBUG fprintf(stderr, "[D] parse_json | cursor = line_start = '%s'\n", cursor); #endif // Decrement from global remaining now, since we'll be consuming this line. remaining -= line_remaining; //// // Get OP //// if (NULL == (delim = strnchr(cursor, ' ', (uint32_t)(line_remaining)))) { #ifdef DEBUG fprintf(stderr, "[E] parse_json | cannot find OP delim\n"); #endif ret = ERRNO_MALFORMED_JSON; goto bail; } consumed = delim - cursor; line_remaining -= consumed; if (SZ_INSN_OP != consumed) { #ifdef DEBUG fprintf(stderr, "[E] parse_json | invalid OP length: %d\n", consumed); #endif ret = ERRNO_MALFORMED_JSON; goto bail; } //// // Dispatch OP //// op = cursor; cursor += SZ_INSN_OP+1; if (0 == memcmp("NEW", op, SZ_INSN_OP)) { if (SUCCESS != (ret = op_new(&cursor, &line_remaining))) { #ifdef DEBUG fprintf(stderr, "[E] parse_json | NEW | non-SUCCESS from op_new()\n"); #endif goto bail; } } else if (0 == memcmp("SET", op, SZ_INSN_OP)) { if (SUCCESS != (ret = op_set(&cursor, &line_remaining))) { #ifdef DEBUG fprintf(stderr, "[E] parse_json | NEW | non-SUCCESS from op_set()\n"); #endif goto bail; } } else if (0 == memcmp("DEL", op, SZ_INSN_OP)) { if (SUCCESS != (ret = op_del(&cursor, &line_remaining))) { #ifdef DEBUG fprintf(stderr, "[E] parse_json | NEW | non-SUCCESS from op_del()\n"); #endif goto bail; } } else { #ifdef DEBUG fprintf(stderr, "[E] parse_json | unknown OP: '%.3s'\n", cursor); #endif ret = ERRNO_MALFORMED_JSON; goto bail; } } bail: return ret; }