You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lnav/src/elem_to_json.cc

216 lines
6.6 KiB
C++

/**
* Copyright (c) 2016, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <algorithm>
#include "elem_to_json.hh"
#include "config.h"
#include "yajlpp/yajlpp.hh"
using namespace std;
static void
element_to_json(yajl_gen gen, data_parser& dp, const data_parser::element& elem)
{
size_t value_len;
const char* value_str = dp.get_element_string(elem, value_len);
switch (elem.value_token()) {
case DT_NUMBER: {
yajl_gen_number(gen, value_str, value_len);
break;
}
case DNT_GROUP: {
elements_to_json(
gen, dp, elem.get_value_elem().e_sub_elements, false);
break;
}
case DNT_PAIR: {
const data_parser::element& pair_elem = elem.get_pair_elem();
string key_str
= dp.get_element_string(pair_elem.e_sub_elements->front());
if (!key_str.empty()) {
yajlpp_map singleton_map(gen);
singleton_map.gen(key_str);
element_to_json(gen, dp, pair_elem.get_pair_value());
} else {
element_to_json(gen, dp, pair_elem.get_pair_value());
}
break;
}
case DT_CONSTANT: {
if (strncasecmp("true", value_str, value_len) == 0) {
yajl_gen_bool(gen, true);
} else if (strncasecmp("false", value_str, value_len) == 0) {
yajl_gen_bool(gen, false);
} else {
yajl_gen_null(gen);
}
break;
}
default:
yajl_gen_pstring(gen, value_str, value_len);
break;
}
}
static void
map_elements_to_json2(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el)
{
yajlpp_map root_map(gen);
int col = 0;
for (auto& iter : *el) {
const data_parser::element& pvalue = iter.get_pair_value();
if (pvalue.value_token() == DT_INVALID) {
log_debug("invalid!!");
// continue;
}
std::string key_str
= dp.get_element_string(iter.e_sub_elements->front());
if (key_str.empty()) {
char buffer[32];
snprintf(buffer, sizeof(buffer), "col_%d", col);
key_str = buffer;
col += 1;
}
root_map.gen(key_str);
element_to_json(gen, dp, pvalue);
}
}
static void
list_body_elements_to_json(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el)
{
for (auto& iter : *el) {
element_to_json(gen, dp, iter);
}
}
static void
list_elements_to_json(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el)
{
yajlpp_array root_array(gen);
list_body_elements_to_json(gen, dp, el);
}
static void
map_elements_to_json(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el)
{
bool unique_names = el->size() > 1;
vector<string> names;
for (auto& iter : *el) {
const data_parser::element& pvalue = iter.get_pair_value();
if (pvalue.value_token() == DT_INVALID) {
log_debug("invalid!!");
// continue;
}
std::string key_str
= dp.get_element_string(iter.e_sub_elements->front());
if (key_str.empty()) {
continue;
}
if (find(names.begin(), names.end(), key_str) != names.end()) {
unique_names = false;
break;
} else {
names.push_back(key_str);
}
}
names.clear();
if (unique_names) {
map_elements_to_json2(gen, dp, el);
} else {
list_elements_to_json(gen, dp, el);
}
}
void
elements_to_json(yajl_gen gen,
data_parser& dp,
data_parser::element_list_t* el,
bool root)
{
if (el->empty()) {
yajl_gen_null(gen);
} else {
switch (el->front().e_token) {
case DNT_PAIR: {
if (root && el->size() == 1) {
const data_parser::element& pair_elem
= el->front().get_pair_elem();
std::string key_str = dp.get_element_string(
pair_elem.e_sub_elements->front());
if (key_str.empty()
&& el->front().get_pair_value().value_token()
== DNT_GROUP) {
element_to_json(gen, dp, el->front().get_pair_value());
} else {
yajlpp_map singleton_map(gen);
if (key_str.empty()) {
key_str = "col_0";
}
singleton_map.gen(key_str);
element_to_json(gen, dp, pair_elem.get_pair_value());
}
} else {
map_elements_to_json(gen, dp, el);
}
break;
}
default:
list_elements_to_json(gen, dp, el);
break;
}
}
}