Jiří Kalvoda
2 years ago
2 changed files with 674 additions and 0 deletions
@ -0,0 +1,203 @@ |
|||
#include "jsmn.h" |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
#include <vector> |
|||
#include <cassert> |
|||
|
|||
using std::vector; |
|||
|
|||
// Parsování JSONu
|
|||
|
|||
static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { |
|||
if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && |
|||
strncmp(json + tok->start, s, tok->end - tok->start) == 0) { |
|||
return 0; |
|||
} |
|||
return -1; |
|||
} |
|||
|
|||
// Třídy reprezentující hru
|
|||
|
|||
enum Direction |
|||
{ |
|||
STAY = -1, |
|||
UP = 0, |
|||
LEFT = 1, |
|||
DOWN = 2, |
|||
RIGHT = 3, |
|||
}; |
|||
|
|||
struct Team; |
|||
struct Member; |
|||
struct Field; |
|||
|
|||
struct Team |
|||
{ |
|||
int id; |
|||
bool is_me; |
|||
Field* home; |
|||
vector<Field*> occupied; |
|||
vector<Field*> protected_fields; |
|||
vector<Member*> members; |
|||
Team(int _id, bool _is_me) |
|||
{ |
|||
id = id; |
|||
is_me = _is_me; |
|||
} |
|||
}; |
|||
|
|||
struct Member |
|||
{ |
|||
Field * field; |
|||
Team * team; |
|||
int id; |
|||
Direction action = STAY; |
|||
Member(Field *_field) |
|||
{ |
|||
field = _field; |
|||
} |
|||
}; |
|||
|
|||
struct Field |
|||
{ |
|||
int i,j; |
|||
bool hill; |
|||
Team* home_for_team = NULL; |
|||
Team* occupied_by_team = NULL; |
|||
Team* protected_for_team = NULL; |
|||
vector<Member*> members; |
|||
Field(int _i, int _j) |
|||
{ |
|||
i = _i; |
|||
j = _j; |
|||
} |
|||
}; |
|||
|
|||
// Celý stav hry včetně parsování a vypisování
|
|||
struct State |
|||
{ |
|||
// Dealokace paměti není implementována, protože předpokládáme, že program
|
|||
// poběží jen krátce a po ukončení všechna paměť automaticky zanikne.
|
|||
vector<Team*> teams; |
|||
vector<vector<Field*>> world; |
|||
Team * my_team; |
|||
int round_number; |
|||
int time_to_response; |
|||
|
|||
int js_skip(jsmntok_t* t, int i) |
|||
{ |
|||
int s = t[i].size; |
|||
i++; |
|||
for(int j=0; j<s; j++) |
|||
i = js_skip(t, i); |
|||
return i; |
|||
} |
|||
|
|||
State(char * input_str) |
|||
{ |
|||
int r; |
|||
jsmn_parser p; |
|||
jsmntok_t t[10000]; /* We expect no more than this count of tokens (jsmn limitation)*/ |
|||
|
|||
jsmn_init(&p); |
|||
r = jsmn_parse(&p, input_str, strlen(input_str), t, |
|||
sizeof(t) / sizeof(t[0])); |
|||
assert(!(r < 0)); |
|||
|
|||
assert(!(r < 1 || t[0].type != JSMN_OBJECT)); |
|||
|
|||
int teams_count, team_id; |
|||
int state_tok, world_tok; |
|||
for (int i = 1, c=0; c < t[0].size;i = js_skip(t, i), c++) |
|||
{ |
|||
//printf("- %.*s %d\n", t[i].end - t[i].start, input_str + t[i].start, t[i].size);
|
|||
|
|||
if (jsoneq(input_str, &t[i], "teams_count") == 0) |
|||
teams_count = atoi(input_str + t[i+1].start); |
|||
if (jsoneq(input_str, &t[i], "team_id") == 0) |
|||
team_id = atoi(input_str + t[i+1].start); |
|||
if (jsoneq(input_str, &t[i], "time_to_response") == 0) |
|||
time_to_response = atoi(input_str + t[i+1].start); |
|||
if (jsoneq(input_str, &t[i], "round_number") == 0) |
|||
round_number = atoi(input_str + t[i+1].start); |
|||
if (jsoneq(input_str, &t[i], "state") == 0) |
|||
state_tok = i+1; |
|||
; |
|||
} |
|||
assert(state_tok); |
|||
printf("%d", teams_count); |
|||
for(int i=0; i<teams_count; i++) |
|||
{ |
|||
teams.push_back(new Team(i, i==team_id)); |
|||
} |
|||
for (int i = state_tok+1, c=0; c < t[state_tok].size;i = js_skip(t, i), c++) |
|||
{ |
|||
if (jsoneq(input_str, &t[i], "world") == 0) |
|||
world_tok = i+1; |
|||
; |
|||
} |
|||
assert(world_tok); |
|||
for (int i = world_tok+1, x=0; x < t[world_tok].size;i = js_skip(t, i), x++) |
|||
{ |
|||
vector<Field *> current_row; |
|||
for (int j = i+1, y=0; y < t[i].size;j = js_skip(t, j), y++) |
|||
{ |
|||
Field *current_field = new Field(x,y); |
|||
int members_tok; |
|||
for (int k = j+1, c=0; c < t[j].size;k = js_skip(t, k), c++) |
|||
{ |
|||
if (jsoneq(input_str, &t[k], "hill") == 0) |
|||
current_field->hill = input_str[t[k+1].start] == 't'; |
|||
if (jsoneq(input_str, &t[k], "home_for_team") == 0) |
|||
if(input_str[t[k+1].start] != 'n') |
|||
current_field->home_for_team = teams[atoi(input_str+t[k+1].start)]; |
|||
if (jsoneq(input_str, &t[k], "occupied_by_team") == 0) |
|||
if(input_str[t[k+1].start] != 'n') |
|||
current_field->occupied_by_team = teams[atoi(input_str+t[k+1].start)]; |
|||
if (jsoneq(input_str, &t[k], "protected_for_team") == 0) |
|||
if(input_str[t[k+1].start] != 'n') |
|||
current_field->protected_for_team = teams[atoi(input_str+t[k+1].start)]; |
|||
if (jsoneq(input_str, &t[k], "members") == 0) |
|||
members_tok = k+1; |
|||
} |
|||
for (int k = members_tok+1, c=0; c < t[members_tok].size;k = js_skip(t, k), c++) |
|||
{ |
|||
auto m = new Member(current_field); |
|||
for (int l = k+1, d=0; d < t[k].size;l = js_skip(t, l), d++) |
|||
{ |
|||
// printf("%d %d: %.*s %d\n", x,y, t[l].end - t[l].start, input_str + t[l].start, t[l].size);
|
|||
if (jsoneq(input_str, &t[l], "id") == 0) |
|||
m->id = atoi(input_str + t[l+1].start); |
|||
if (jsoneq(input_str, &t[l], "team") == 0) |
|||
m->team = teams[atoi(input_str+t[l+1].start)]; |
|||
} |
|||
current_field->members.push_back(m); |
|||
} |
|||
current_row.push_back(current_field); |
|||
} |
|||
world.push_back(current_row); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
State* state; |
|||
|
|||
|
|||
|
|||
// Algoritmy
|
|||
|
|||
// main (zde doplňte kód)
|
|||
|
|||
void load() |
|||
{ |
|||
char * input_str; |
|||
scanf("%m[^\n]", &input_str); |
|||
state = new State(input_str); |
|||
} |
|||
|
|||
int main() |
|||
{ |
|||
load(); |
|||
return 0; |
|||
} |
@ -0,0 +1,471 @@ |
|||
/*
|
|||
* MIT License |
|||
* |
|||
* Copyright (c) 2010 Serge Zaitsev |
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
* SOFTWARE. |
|||
*/ |
|||
#ifndef JSMN_H |
|||
#define JSMN_H |
|||
|
|||
#include <stddef.h> |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
#ifdef JSMN_STATIC |
|||
#define JSMN_API static |
|||
#else |
|||
#define JSMN_API extern |
|||
#endif |
|||
|
|||
/**
|
|||
* JSON type identifier. Basic types are: |
|||
* o Object |
|||
* o Array |
|||
* o String |
|||
* o Other primitive: number, boolean (true/false) or null |
|||
*/ |
|||
typedef enum { |
|||
JSMN_UNDEFINED = 0, |
|||
JSMN_OBJECT = 1 << 0, |
|||
JSMN_ARRAY = 1 << 1, |
|||
JSMN_STRING = 1 << 2, |
|||
JSMN_PRIMITIVE = 1 << 3 |
|||
} jsmntype_t; |
|||
|
|||
enum jsmnerr { |
|||
/* Not enough tokens were provided */ |
|||
JSMN_ERROR_NOMEM = -1, |
|||
/* Invalid character inside JSON string */ |
|||
JSMN_ERROR_INVAL = -2, |
|||
/* The string is not a full JSON packet, more bytes expected */ |
|||
JSMN_ERROR_PART = -3 |
|||
}; |
|||
|
|||
/**
|
|||
* JSON token description. |
|||
* type type (object, array, string etc.) |
|||
* start start position in JSON data string |
|||
* end end position in JSON data string |
|||
*/ |
|||
typedef struct jsmntok { |
|||
jsmntype_t type; |
|||
int start; |
|||
int end; |
|||
int size; |
|||
#ifdef JSMN_PARENT_LINKS |
|||
int parent; |
|||
#endif |
|||
} jsmntok_t; |
|||
|
|||
/**
|
|||
* JSON parser. Contains an array of token blocks available. Also stores |
|||
* the string being parsed now and current position in that string. |
|||
*/ |
|||
typedef struct jsmn_parser { |
|||
unsigned int pos; /* offset in the JSON string */ |
|||
unsigned int toknext; /* next token to allocate */ |
|||
int toksuper; /* superior token node, e.g. parent object or array */ |
|||
} jsmn_parser; |
|||
|
|||
/**
|
|||
* Create JSON parser over an array of tokens |
|||
*/ |
|||
JSMN_API void jsmn_init(jsmn_parser *parser); |
|||
|
|||
/**
|
|||
* Run JSON parser. It parses a JSON data string into and array of tokens, each |
|||
* describing |
|||
* a single JSON object. |
|||
*/ |
|||
JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, |
|||
jsmntok_t *tokens, const unsigned int num_tokens); |
|||
|
|||
#ifndef JSMN_HEADER |
|||
/**
|
|||
* Allocates a fresh unused token from the token pool. |
|||
*/ |
|||
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, |
|||
const size_t num_tokens) { |
|||
jsmntok_t *tok; |
|||
if (parser->toknext >= num_tokens) { |
|||
return NULL; |
|||
} |
|||
tok = &tokens[parser->toknext++]; |
|||
tok->start = tok->end = -1; |
|||
tok->size = 0; |
|||
#ifdef JSMN_PARENT_LINKS |
|||
tok->parent = -1; |
|||
#endif |
|||
return tok; |
|||
} |
|||
|
|||
/**
|
|||
* Fills token type and boundaries. |
|||
*/ |
|||
static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, |
|||
const int start, const int end) { |
|||
token->type = type; |
|||
token->start = start; |
|||
token->end = end; |
|||
token->size = 0; |
|||
} |
|||
|
|||
/**
|
|||
* Fills next available token with JSON primitive. |
|||
*/ |
|||
static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, |
|||
const size_t len, jsmntok_t *tokens, |
|||
const size_t num_tokens) { |
|||
jsmntok_t *token; |
|||
int start; |
|||
|
|||
start = parser->pos; |
|||
|
|||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { |
|||
switch (js[parser->pos]) { |
|||
#ifndef JSMN_STRICT |
|||
/* In strict mode primitive must be followed by "," or "}" or "]" */ |
|||
case ':': |
|||
#endif |
|||
case '\t': |
|||
case '\r': |
|||
case '\n': |
|||
case ' ': |
|||
case ',': |
|||
case ']': |
|||
case '}': |
|||
goto found; |
|||
default: |
|||
/* to quiet a warning from gcc*/ |
|||
break; |
|||
} |
|||
if (js[parser->pos] < 32 || js[parser->pos] >= 127) { |
|||
parser->pos = start; |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
} |
|||
#ifdef JSMN_STRICT |
|||
/* In strict mode primitive must be followed by a comma/object/array */ |
|||
parser->pos = start; |
|||
return JSMN_ERROR_PART; |
|||
#endif |
|||
|
|||
found: |
|||
if (tokens == NULL) { |
|||
parser->pos--; |
|||
return 0; |
|||
} |
|||
token = jsmn_alloc_token(parser, tokens, num_tokens); |
|||
if (token == NULL) { |
|||
parser->pos = start; |
|||
return JSMN_ERROR_NOMEM; |
|||
} |
|||
jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); |
|||
#ifdef JSMN_PARENT_LINKS |
|||
token->parent = parser->toksuper; |
|||
#endif |
|||
parser->pos--; |
|||
return 0; |
|||
} |
|||
|
|||
/**
|
|||
* Fills next token with JSON string. |
|||
*/ |
|||
static int jsmn_parse_string(jsmn_parser *parser, const char *js, |
|||
const size_t len, jsmntok_t *tokens, |
|||
const size_t num_tokens) { |
|||
jsmntok_t *token; |
|||
|
|||
int start = parser->pos; |
|||
|
|||
/* Skip starting quote */ |
|||
parser->pos++; |
|||
|
|||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { |
|||
char c = js[parser->pos]; |
|||
|
|||
/* Quote: end of string */ |
|||
if (c == '\"') { |
|||
if (tokens == NULL) { |
|||
return 0; |
|||
} |
|||
token = jsmn_alloc_token(parser, tokens, num_tokens); |
|||
if (token == NULL) { |
|||
parser->pos = start; |
|||
return JSMN_ERROR_NOMEM; |
|||
} |
|||
jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); |
|||
#ifdef JSMN_PARENT_LINKS |
|||
token->parent = parser->toksuper; |
|||
#endif |
|||
return 0; |
|||
} |
|||
|
|||
/* Backslash: Quoted symbol expected */ |
|||
if (c == '\\' && parser->pos + 1 < len) { |
|||
int i; |
|||
parser->pos++; |
|||
switch (js[parser->pos]) { |
|||
/* Allowed escaped symbols */ |
|||
case '\"': |
|||
case '/': |
|||
case '\\': |
|||
case 'b': |
|||
case 'f': |
|||
case 'r': |
|||
case 'n': |
|||
case 't': |
|||
break; |
|||
/* Allows escaped symbol \uXXXX */ |
|||
case 'u': |
|||
parser->pos++; |
|||
for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; |
|||
i++) { |
|||
/* If it isn't a hex character we have an error */ |
|||
if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ |
|||
(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ |
|||
(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ |
|||
parser->pos = start; |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
parser->pos++; |
|||
} |
|||
parser->pos--; |
|||
break; |
|||
/* Unexpected symbol */ |
|||
default: |
|||
parser->pos = start; |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
} |
|||
} |
|||
parser->pos = start; |
|||
return JSMN_ERROR_PART; |
|||
} |
|||
|
|||
/**
|
|||
* Parse JSON string and fill tokens. |
|||
*/ |
|||
JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, |
|||
jsmntok_t *tokens, const unsigned int num_tokens) { |
|||
int r; |
|||
int i; |
|||
jsmntok_t *token; |
|||
int count = parser->toknext; |
|||
|
|||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { |
|||
char c; |
|||
jsmntype_t type; |
|||
|
|||
c = js[parser->pos]; |
|||
switch (c) { |
|||
case '{': |
|||
case '[': |
|||
count++; |
|||
if (tokens == NULL) { |
|||
break; |
|||
} |
|||
token = jsmn_alloc_token(parser, tokens, num_tokens); |
|||
if (token == NULL) { |
|||
return JSMN_ERROR_NOMEM; |
|||
} |
|||
if (parser->toksuper != -1) { |
|||
jsmntok_t *t = &tokens[parser->toksuper]; |
|||
#ifdef JSMN_STRICT |
|||
/* In strict mode an object or array can't become a key */ |
|||
if (t->type == JSMN_OBJECT) { |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
#endif |
|||
t->size++; |
|||
#ifdef JSMN_PARENT_LINKS |
|||
token->parent = parser->toksuper; |
|||
#endif |
|||
} |
|||
token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); |
|||
token->start = parser->pos; |
|||
parser->toksuper = parser->toknext - 1; |
|||
break; |
|||
case '}': |
|||
case ']': |
|||
if (tokens == NULL) { |
|||
break; |
|||
} |
|||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); |
|||
#ifdef JSMN_PARENT_LINKS |
|||
if (parser->toknext < 1) { |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
token = &tokens[parser->toknext - 1]; |
|||
for (;;) { |
|||
if (token->start != -1 && token->end == -1) { |
|||
if (token->type != type) { |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
token->end = parser->pos + 1; |
|||
parser->toksuper = token->parent; |
|||
break; |
|||
} |
|||
if (token->parent == -1) { |
|||
if (token->type != type || parser->toksuper == -1) { |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
break; |
|||
} |
|||
token = &tokens[token->parent]; |
|||
} |
|||
#else |
|||
for (i = parser->toknext - 1; i >= 0; i--) { |
|||
token = &tokens[i]; |
|||
if (token->start != -1 && token->end == -1) { |
|||
if (token->type != type) { |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
parser->toksuper = -1; |
|||
token->end = parser->pos + 1; |
|||
break; |
|||
} |
|||
} |
|||
/* Error if unmatched closing bracket */ |
|||
if (i == -1) { |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
for (; i >= 0; i--) { |
|||
token = &tokens[i]; |
|||
if (token->start != -1 && token->end == -1) { |
|||
parser->toksuper = i; |
|||
break; |
|||
} |
|||
} |
|||
#endif |
|||
break; |
|||
case '\"': |
|||
r = jsmn_parse_string(parser, js, len, tokens, num_tokens); |
|||
if (r < 0) { |
|||
return r; |
|||
} |
|||
count++; |
|||
if (parser->toksuper != -1 && tokens != NULL) { |
|||
tokens[parser->toksuper].size++; |
|||
} |
|||
break; |
|||
case '\t': |
|||
case '\r': |
|||
case '\n': |
|||
case ' ': |
|||
break; |
|||
case ':': |
|||
parser->toksuper = parser->toknext - 1; |
|||
break; |
|||
case ',': |
|||
if (tokens != NULL && parser->toksuper != -1 && |
|||
tokens[parser->toksuper].type != JSMN_ARRAY && |
|||
tokens[parser->toksuper].type != JSMN_OBJECT) { |
|||
#ifdef JSMN_PARENT_LINKS |
|||
parser->toksuper = tokens[parser->toksuper].parent; |
|||
#else |
|||
for (i = parser->toknext - 1; i >= 0; i--) { |
|||
if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { |
|||
if (tokens[i].start != -1 && tokens[i].end == -1) { |
|||
parser->toksuper = i; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
#endif |
|||
} |
|||
break; |
|||
#ifdef JSMN_STRICT |
|||
/* In strict mode primitives are: numbers and booleans */ |
|||
case '-': |
|||
case '0': |
|||
case '1': |
|||
case '2': |
|||
case '3': |
|||
case '4': |
|||
case '5': |
|||
case '6': |
|||
case '7': |
|||
case '8': |
|||
case '9': |
|||
case 't': |
|||
case 'f': |
|||
case 'n': |
|||
/* And they must not be keys of the object */ |
|||
if (tokens != NULL && parser->toksuper != -1) { |
|||
const jsmntok_t *t = &tokens[parser->toksuper]; |
|||
if (t->type == JSMN_OBJECT || |
|||
(t->type == JSMN_STRING && t->size != 0)) { |
|||
return JSMN_ERROR_INVAL; |
|||
} |
|||
} |
|||
#else |
|||
/* In non-strict mode every unquoted value is a primitive */ |
|||
default: |
|||
#endif |
|||
r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); |
|||
if (r < 0) { |
|||
return r; |
|||
} |
|||
count++; |
|||
if (parser->toksuper != -1 && tokens != NULL) { |
|||
tokens[parser->toksuper].size++; |
|||
} |
|||
break; |
|||
|
|||
#ifdef JSMN_STRICT |
|||
/* Unexpected char in strict mode */ |
|||
default: |
|||
return JSMN_ERROR_INVAL; |
|||
#endif |
|||
} |
|||
} |
|||
|
|||
if (tokens != NULL) { |
|||
for (i = parser->toknext - 1; i >= 0; i--) { |
|||
/* Unmatched opened object or array */ |
|||
if (tokens[i].start != -1 && tokens[i].end == -1) { |
|||
return JSMN_ERROR_PART; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return count; |
|||
} |
|||
|
|||
/**
|
|||
* Creates a new parser based over a given buffer with an array of tokens |
|||
* available. |
|||
*/ |
|||
JSMN_API void jsmn_init(jsmn_parser *parser) { |
|||
parser->pos = 0; |
|||
parser->toknext = 0; |
|||
parser->toksuper = -1; |
|||
} |
|||
|
|||
#endif /* JSMN_HEADER */ |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif /* JSMN_H */ |
Loading…
Reference in new issue