Skip to content
This repository has been archived by the owner on Sep 12, 2023. It is now read-only.

Commit

Permalink
eni_json
Browse files Browse the repository at this point in the history
  • Loading branch information
afg committed Jun 13, 2019
1 parent 321d959 commit e83592e
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "examples/eni/json/jsmn"]
path = examples/eni/json/jsmn
url = https://github.com/zserge/jsmn
5 changes: 5 additions & 0 deletions examples/eni/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ add_eni_library(eni_reverse
SRCS reverse/eni_reverse.cpp
LIBS eni
)

add_eni_library(eni_json
SRCS json/eni_json.cpp
LIBS eni
)
137 changes: 137 additions & 0 deletions examples/eni/json/eni_json.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*==- examples/eni/reverse/eni_reverse.cpp ---------------------------------==
This file is part of the Lity project distributed under GPL-3.0.
See LICENSE for details.
==------------------------------------------------------------------------==*/
#include <eni.h>
#include <json/Parser.h>

#include "jsmn/jsmn.h"

namespace {
std::string parseString(const std::string& raw) { return json::Parser(raw).getRoot().toString(); }
std::vector<jsmntok_t> internalParse(const char* data, int start, int end) {
jsmn_parser p;
p.pos = start;
p.toknext = 0;
p.toksuper = -1;
int len = jsmn_parse(&p, data, end, 0, 0);
std::vector<jsmntok_t> result(len);
p.pos = start;
p.toknext = 0;
p.toksuper = -1;
jsmn_parse(&p, data, end, result.data(), len);
return result;
}
std::string encodeToken(const jsmntok_t& tok) {
union {
char s[8];
uint32_t v[2];
};
v[0] = htobe32(tok.start - (tok.type == JSMN_STRING));
v[1] = htobe32(tok.end + (tok.type == JSMN_STRING));
return std::string(s, 8);
}
std::vector<jsmntok_t> arrayTokens(const char* data, int start, int end) {
auto tokens = internalParse(data, start, end);
std::vector<jsmntok_t> result;
int after = tokens[0].start;
int before = tokens[0].end;
for (int i = 1; i < tokens.size(); i++) {
if (tokens[i].start < after) {
continue;
}
if (tokens[i].start > before) {
break;
}
result.push_back(tokens[i]);
after = tokens[i].end;
}
return result;
}
std::string parseArray(const char* data, int start, int end) {
std::string result;
for (const auto& tok: arrayTokens(data, start, end)) {
result += encodeToken(tok);
}
return result;
}
std::string arrayGet(const char* data, int start, int end, int index) {
auto tokens = arrayTokens(data, start, end);
return encodeToken(tokens[index]);
}

std::map<std::string, jsmntok_t> objectTokens(const char* data, int start, int end) {
auto tokens = internalParse(data, start, end);
std::map<std::string, jsmntok_t> result;
int after = tokens[0].start;
int before = tokens[0].end;
int key_token = 0;
auto getkey = [&] {
auto& tok = tokens[key_token];
return parseString(std::string(data + tok.start - 1, data + tok.end + 1));
};
for (int i = 1; i < tokens.size(); i++) {
if (tokens[i].start < after) {
continue;
}
if (tokens[i].start > before) {
break;
}
if (key_token == 0) {
key_token = i;
} else {
result[getkey()] = tokens[i];
}
after = tokens[i].end;
}
return result;
}

std::string objectGet(const char* data, int start, int end, const std::string& key) {
auto tokens = objectTokens(data, start, end);
return encodeToken(tokens[key]);
}
} // namespace

class JSON : public eni::EniBase {
public:
JSON(const std::string& pArgStr) : eni::EniBase(pArgStr) {}

~JSON() {}

private:
bool parse(const json::Array& pArgs) override {
std::string op = pArgs[0].toString();
std::string data = pArgs[1].toString();
int begin = (int)pArgs[2].toInteger();
int end = (int)pArgs[3].toInteger();
if (op == "parseString") {
m_Str = parseString(std::string(data.data(), begin, end));
} else if (op == "parseArray") {
m_Str = parseArray(data.data(), begin, end);
} else if (op == "arrayGet") {
m_Str = arrayGet(data.data(), begin, end, (int)pArgs[4].toInteger());
} else if (op == "objectGet") {
m_Str = objectGet(data.data(), begin, end, pArgs[4].toString());
} else {
return false;
}
m_Str = pArgs[0].toString();
return true;
}

eni::Gas gas() const override { return 0; }

bool run(json::Array& pRetVal) override {
std::string ret(m_Str.rbegin(), m_Str.rend());
pRetVal.emplace_back(ret);
return true;
}

private:
std::string m_Str;
};

ENI_C_INTERFACE(json, JSON)
1 change: 1 addition & 0 deletions examples/eni/json/jsmn
Submodule jsmn added at fdcef3

0 comments on commit e83592e

Please sign in to comment.