Skip to content

Instantly share code, notes, and snippets.

@xerpi
Last active November 12, 2016 08:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xerpi/eb49b34f7bc43f90194c0a16bbf0e623 to your computer and use it in GitHub Desktop.
Save xerpi/eb49b34f7bc43f90194c0a16bbf0e623 to your computer and use it in GitHub Desktop.
/*
* vitajsonlinker by xerpi
* - ./vitajsonlinker db1.json [db2.json, ...]
*/
#include <string>
#include <list>
#include <iostream>
#include <jansson.h>
typedef uint32_t vita_nid_t;
struct vita_function_t {
std::string name;
vita_nid_t nid;
};
struct vita_variable_t {
std::string name;
vita_nid_t nid;
};
struct vita_library_t {
std::string name;
vita_nid_t nid;
bool visibility;
std::list<vita_function_t> functions;
std::list<vita_variable_t> variables;
};
struct vita_module_t {
std::string name;
vita_nid_t nid;
bool privilege;
std::list<vita_library_t> libraries;
};
struct vita_exports_t {
std::list<vita_module_t> modules;
};
void vita_exports_remove_empty(vita_exports_t &exports)
{
for (std::list<vita_module_t>::iterator mod = exports.modules.begin(); mod != exports.modules.end(); ) {
for (std::list<vita_library_t>::iterator lib = mod->libraries.begin(); lib != mod->libraries.end(); ) {
if (lib->functions.size() == 0 && lib->variables.size() == 0) {
lib = mod->libraries.erase(lib);
continue;
}
lib++;
}
if (mod->libraries.size() == 0) {
mod = exports.modules.erase(mod);
continue;
}
mod++;
}
}
void vita_exports_sort(vita_exports_t &exports)
{
std::list<vita_module_t>::iterator mod_it;
for (mod_it = exports.modules.begin(); mod_it != exports.modules.end(); mod_it++) {
std::list<vita_library_t>::iterator lib_it;
for (lib_it = mod_it->libraries.begin(); lib_it != mod_it->libraries.end(); lib_it++) {
lib_it->functions.sort([](const vita_function_t &a, const vita_function_t &b) {
return a.name < b.name;
});
lib_it->variables.sort([](const vita_variable_t &a, const vita_variable_t &b) {
return a.name < b.name;
});
}
mod_it->libraries.sort([](const vita_library_t &a, const vita_library_t &b) {
return a.name < b.name;
});
}
exports.modules.sort([](const vita_module_t &a, const vita_module_t &b) {
return a.name < b.name;
});
}
void vita_json_print(const vita_exports_t &exports)
{
std::cout << "{" << std::endl;
std::list<vita_module_t>::const_iterator mod_it;
for (mod_it = exports.modules.begin(); mod_it != exports.modules.end(); mod_it++) {
std::cout << "\t\"" << mod_it->name << "\": {" << std::endl;
std::cout << "\t\t\"nid\": " << mod_it->nid << "," << std::endl;
std::cout << "\t\t\"" << "modules" << "\": {" << std::endl;
std::list<vita_library_t>::const_iterator lib_it;
for (lib_it = mod_it->libraries.begin(); lib_it != mod_it->libraries.end(); lib_it++) {
std::cout << "\t\t\t\"" << lib_it->name << "\": {" << std::endl;
std::cout << "\t\t\t\t\"kernel\": " << (lib_it->visibility ? "true" : "false") << "," << std::endl;
std::cout << "\t\t\t\t\"nid\": " << lib_it->nid << "," << std::endl;
std::cout << "\t\t\t\t\"" << "functions" << "\": {" << std::endl;
std::list<vita_function_t>::const_iterator func_it;
for (func_it = lib_it->functions.begin(); func_it != lib_it->functions.end(); func_it++) {
std::cout << "\t\t\t\t\t\"" << func_it->name << "\": " << func_it->nid;
if (func_it != std::prev(lib_it->functions.end()))
std::cout << ",";
std::cout << std::endl;
}
std::cout << "\t\t\t\t}" << std::endl;
std::cout << "\t\t\t}";
if (lib_it != std::prev(mod_it->libraries.end()))
std::cout << ",";
std::cout << std::endl;
}
std::cout << "\t\t}" << std::endl;
std::cout << "\t}";
if (mod_it != std::prev(exports.modules.end()))
std::cout << ",";
std::cout << std::endl;
}
std::cout << "}" << std::endl;
}
bool vita_json_load(vita_exports_t &exports, FILE *file, int verbose)
{
json_t *libs, *lib_data;
json_error_t error;
const char *lib_name, *mod_name, *target_name;
libs = json_loadf(file, 0, &error);
if (libs == nullptr) {
fprintf(stderr, "error: on line %d: %s\n", error.line, error.text);
return false;
}
if (!json_is_object(libs)) {
fprintf(stderr, "error: modules is not an object\n");
json_decref(libs);
return false;
}
int i, j, k;
i = -1;
json_object_foreach(libs, lib_name, lib_data) {
json_t *nid, *modules, *mod_data;
i++;
if (!json_is_object(lib_data)) {
fprintf(stderr, "error: library %s is not an object\n", lib_name);
json_decref(libs);
return false;
}
nid = json_object_get(lib_data, "nid");
if (!json_is_integer(nid)) {
fprintf(stderr, "error: library %s: nid is not an integer\n", lib_name);
json_decref(libs);
return false;
}
modules = json_object_get(lib_data, "modules");
if (!json_is_object(modules)) {
fprintf(stderr, "error: library %s: module is not an object\n", lib_name);
json_decref(libs);
return false;
}
std::string module_name = std::string(lib_name);
vita_nid_t module_nid = json_integer_value(nid);
std::list<vita_module_t>::iterator mod_it;
for (mod_it = exports.modules.begin(); mod_it != exports.modules.end(); mod_it++) {
if (mod_it->name.compare(module_name) == 0) {
/*
* If we have found the *real* NID, update
* the fake one (nids from 0 to a few hundreds).
*/
if (mod_it->nid < 500 && module_nid > 500)
mod_it->nid = module_nid;
break;
}
}
if (mod_it == exports.modules.end()) {
vita_module_t module;
module.name = module_name;
module.nid = module_nid;
//module.visibility = ?;
exports.modules.push_back(module);
mod_it = std::prev(exports.modules.end());
}
if (verbose)
printf("Lib: %s\n", lib_name);
j = -1;
json_object_foreach(modules, mod_name, mod_data) {
json_t *nid, *kernel, *functions, *variables, *target_nid;
bool has_variables = true;
j++;
if (!json_is_object(mod_data)) {
fprintf(stderr, "error: module %s is not an object\n", mod_name);
json_decref(libs);
return false;
}
nid = json_object_get(mod_data, "nid");
if (!json_is_integer(nid)) {
fprintf(stderr, "error: module %s: nid is not an integer\n", mod_name);
json_decref(libs);
return false;
}
kernel = json_object_get(mod_data, "kernel");
if (!json_is_boolean(kernel)) {
fprintf(stderr, "error: module %s: kernel is not a boolean\n", mod_name);
json_decref(libs);
return false;
}
functions = json_object_get(mod_data, "functions");
if (!json_is_object(functions)) {
fprintf(stderr, "error: module %s: functions is not an array\n", mod_name);
json_decref(libs);
return false;
}
variables = json_object_get(mod_data, "variables");
if (variables == nullptr) {
has_variables = false;
}
if (has_variables && !json_is_object(variables)) {
fprintf(stderr, "error: module %s: variables is not an array\n", mod_name);
json_decref(libs);
return false;
}
if (verbose)
printf("\tModule: %s\n", mod_name);
std::string library_name = std::string(mod_name);
vita_nid_t library_nid = json_integer_value(nid);
std::list<vita_library_t>::iterator lib_it;
for (lib_it = mod_it->libraries.begin(); lib_it != mod_it->libraries.end(); lib_it++) {
if (lib_it->name.compare(library_name) == 0)
break;
}
if (lib_it == mod_it->libraries.end()) {
vita_library_t library;
library.name = library_name;
library.nid = library_nid;
library.visibility = json_boolean_value(kernel);
mod_it->libraries.push_back(library);
lib_it = std::prev(mod_it->libraries.end());
}
k = -1;
json_object_foreach(functions, target_name, target_nid) {
k++;
if (!json_is_integer(target_nid)) {
fprintf(stderr, "error: function %s: nid is not an integer\n", target_name);
json_decref(libs);
return false;
}
if (verbose)
printf("\t\tFunction: %s\n", target_name);
std::string function_name = std::string(target_name);
vita_nid_t function_nid = json_integer_value(target_nid);
std::list<vita_function_t>::iterator func_it;
for (func_it = lib_it->functions.begin(); func_it != lib_it->functions.end(); func_it++) {
if (func_it->name.compare(function_name) == 0)
break;
}
if (func_it == lib_it->functions.end()) {
vita_function_t function;
function.name = function_name;
function.nid = function_nid;
lib_it->functions.push_back(function);
}
}
if (has_variables) {
k = -1;
json_object_foreach(variables, target_name, target_nid) {
k++;
if (!json_is_integer(target_nid)) {
fprintf(stderr, "error: variable %s: nid is not an integer\n", target_name);
json_decref(libs);
return false;
}
if (verbose)
printf("\t\tVariable: %s\n", target_name);
std::string variable_name = std::string(target_name);
vita_nid_t variable_nid = json_integer_value(target_nid);
std::list<vita_variable_t>::iterator func_it;
for (func_it = lib_it->variables.begin(); func_it != lib_it->variables.end(); func_it++) {
if (func_it->name.compare(variable_name) == 0 && func_it->nid == variable_nid)
break;
}
if (func_it == lib_it->variables.end()) {
vita_variable_t variable;
variable.name = variable_name;
variable.nid = variable_nid;
lib_it->variables.push_back(variable);
}
}
}
}
}
return true;
}
int main(int argc, char *argv[])
{
FILE *fp;
vita_exports_t exports;
if (argc < 2) {
std::cerr << "Usage: vitajsonlinker db1.json [db2.json, ...]" << std::endl;
return 1;
}
for (int i = 1; i < argc; i++) {
fp = fopen(argv[i], "r");
if (fp == nullptr) {
std::cerr << "Error: could not open: " << argv[i] << std::endl;
return 1;
}
vita_json_load(exports, fp, 0);
fclose(fp);
}
vita_exports_remove_empty(exports);
vita_exports_sort(exports);
vita_json_print(exports);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment