← 返回首页
/*
* Copyright (C) 2011-2026 Redis Labs Ltd.
*
* This file is part of memtier_benchmark.
*
* memtier_benchmark is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* memtier_benchmark is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with memtier_benchmark. If not, see .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include
#include // For std::isnan
#include "JSON_handler.h"
/**
* C'tor
* -----
* Opens the file named jsonfilename and sets the first nesting as NESTED_GENERAL
* In case of failure to create the file, will state the error perror
*/
json_handler::json_handler(const char *jsonfilename) : m_json_file(NULL)
{
// Try to open a file and add the first level
m_json_file = fopen(jsonfilename, "w");
if (!m_json_file) {
perror(jsonfilename);
}
// opening the JSON
fprintf(stderr, "Json file %s created...\n", jsonfilename);
fprintf(m_json_file, "{");
m_nest_closer_types.push_back(NESTED_GENERAL);
beutify();
}
/**
* D'tor
* -----
* Closes all the nesting and the file pointer.
*/
json_handler::~json_handler()
{
if (m_json_file) {
// close nesting...
while (close_nesting())
;
fclose(m_json_file);
fprintf(stderr, "Json file closed.\n");
}
}
/**
* Write singel object named objectname to the JSON with values stated in ...
* based on the format defined
* basically uses fprintf with the same parameters.
*/
void json_handler::write_obj(const char *objectname, const char *format, ...)
{
fprintf(m_json_file, "\"%s\": ", objectname);
va_list argptr;
va_start(argptr, format);
// Check if format includes "%s", indicating a string is expected
if (strstr(format, "%s") != nullptr) {
// Use a temporary va_list to check the string argument without advancing the original
va_list tmp_argptr;
va_copy(tmp_argptr, argptr);
const char *str_arg = va_arg(tmp_argptr, const char *);
va_end(tmp_argptr);
if (str_arg == nullptr) {
// Handle NULL strings by writing "null" to the JSON file
fprintf(m_json_file, "null");
} else {
// Print the valid string argument
vfprintf(m_json_file, format, argptr);
}
}
// Check if the format expects a floating-point number
else if (strstr(format, "f") != nullptr || strstr(format, "e") != nullptr || strstr(format, "g") != nullptr) {
va_list tmp_argptr;
va_copy(tmp_argptr, argptr);
double value = va_arg(tmp_argptr, double);
va_end(tmp_argptr);
if (std::isnan(value)) {
fprintf(m_json_file, "null");
} else {
vfprintf(m_json_file, format, argptr);
}
} else {
// For other format specifiers, proceed as usual
vfprintf(m_json_file, format, argptr);
}
va_end(argptr);
beutify();
fprintf(m_json_file, ",");
}
/**
* Starts a nesting with a title as defined in objectname
* in case objectname == NULL it will not add the title and just start nesting
* The type defines the kind of charecters that will be used
*/
void json_handler::open_nesting(const char *objectname, eJSON_NESTED_TYPE type /*= NESTED_GENERAL*/)
{
const char *nestStart = (type == NESTED_GENERAL) ? "{" : "[";
if (objectname != NULL) {
fprintf(m_json_file, "\"%s\":", objectname);
}
fprintf(m_json_file, "%s", nestStart);
// Adding the type to the nesting closer list to be able to close it properly
m_nest_closer_types.push_back(type);
beutify(false);
}
/**
* Ends the nesting
* Closes the nesting based on the nesting list
* Returns = the nested levels left after the closing
*/
int json_handler::close_nesting()
{
int nest_level = m_nest_closer_types.size();
if (nest_level > 0) {
eJSON_NESTED_TYPE type = m_nest_closer_types.back();
m_nest_closer_types.pop_back();
// as we assume that the last value is always a ',' or '\n' we need to remove it first
fseek(m_json_file, -1, SEEK_CUR);
const char *nestEnd = (type == NESTED_GENERAL) ? "}" : "]";
fprintf(m_json_file, "%s", nestEnd);
beutify();
if (nest_level > 1) {
fprintf(m_json_file, ",");
}
}
return m_nest_closer_types.size();
}
/**
* Add tabls and new line (if only_tabs==true will only add tabs)
*/
void json_handler::beutify(bool only_tabs)
{
if (only_tabs == false) {
fprintf(m_json_file, "\n");
}
int nest_level = m_nest_closer_types.size();
for (; nest_level > 0; nest_level--) {
fprintf(m_json_file, "\t");
}
}