#include <config.h>
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <string>
#include "logging.h"
#include "google/jsonwriter.h"
#include "google/output_string.h"
namespace open_vcdiff {
JSONCodeTableWriter::JSONCodeTableWriter()
: output_called_(false), opcode_added_(false) {}
JSONCodeTableWriter::~JSONCodeTableWriter() {}
bool JSONCodeTableWriter::Init(size_t ) {
output_ = "[";
opcode_added_ = false;
return true;
}
void JSONCodeTableWriter::Output(OutputStringInterface* out) {
output_called_ = true;
out->append(output_.data(), output_.size());
output_ = "";
}
void JSONCodeTableWriter::FinishEncoding(OutputStringInterface* out) {
if (output_called_) {
out->append("]", 1);
}
}
void JSONCodeTableWriter::JSONEscape(const char* data,
size_t size,
string* out) {
for (size_t i = 0; i < size; ++i) {
const unsigned char c = static_cast<unsigned char>(data[i]);
switch (c) {
case '"': out->append("\\\"", 2); break;
case '\\': out->append("\\\\", 2); break;
case '\b': out->append("\\b", 2); break;
case '\f': out->append("\\f", 2); break;
case '\n': out->append("\\n", 2); break;
case '\r': out->append("\\r", 2); break;
case '\t': out->append("\\t", 2); break;
default:
if (c < 32 || c >= 127) {
char unicode_code[8] = "";
snprintf(unicode_code, sizeof(unicode_code), "\\u%04x", c);
out->append(unicode_code, strlen(unicode_code));
} else {
out->push_back(data[i]);
}
}
}
}
void JSONCodeTableWriter::Add(const char* data, size_t size) {
if (opcode_added_) {
output_.push_back(',');
}
output_.push_back('\"');
JSONEscape(data, size, &output_);
output_.push_back('\"');
opcode_added_ = true;
}
void JSONCodeTableWriter::Copy(int32_t offset, size_t size) {
if (opcode_added_) {
output_.push_back(',');
}
std::ostringstream copy_code;
copy_code << offset << "," << size;
output_.append(copy_code.str());
opcode_added_ = true;
}
void JSONCodeTableWriter::Run(size_t size, unsigned char byte) {
if (opcode_added_) {
output_.push_back(',');
}
output_.push_back('\"');
output_.append(string(size, byte).data(), size);
output_.push_back('\"');
opcode_added_ = true;
}
void JSONCodeTableWriter::WriteHeader(OutputStringInterface *,
VCDiffFormatExtensionFlags) {
}
bool JSONCodeTableWriter::VerifyDictionary(const char *dictionary,
size_t size) const {
VCD_ERROR << "JSON writer does not allow non-ASCII characters"
" in dictionary" << VCD_ENDL;
return IsAscii(dictionary, size);
}
bool JSONCodeTableWriter::VerifyChunk(const char *chunk, size_t size) const {
VCD_ERROR << "JSON writer does not allow non-ASCII characters"
" in target" << VCD_ENDL;
return IsAscii(chunk, size);
}
bool JSONCodeTableWriter::IsAscii(const char *data, size_t len) {
for (size_t i = 0; i < len; i++) {
if (static_cast<unsigned char>(data[i]) >= 128) {
return false;
}
}
return true;
}
}