1 // Copyright 2009 Google Inc. 2 // Author: James deBoer 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #include <config.h> 17 #include <stdio.h> 18 #include <string.h> 19 #include <sstream> 20 #include <string> 21 #include "jsonwriter.h" 22 #include "google/output_string.h" 23 24 namespace open_vcdiff { 25 26 JSONCodeTableWriter::JSONCodeTableWriter() 27 : output_called_(false) {} 28 JSONCodeTableWriter::~JSONCodeTableWriter() {} 29 30 bool JSONCodeTableWriter::Init(size_t /*dictionary_size*/) { 31 output_ = "["; 32 target_length_ = 0; 33 return true; 34 } 35 36 void JSONCodeTableWriter::Output(OutputStringInterface* out) { 37 output_called_ = true; 38 out->append(output_.data(), output_.size()); 39 output_ = ""; 40 target_length_ = 0; 41 } 42 43 void JSONCodeTableWriter::FinishEncoding(OutputStringInterface* out) { 44 if (output_called_) { 45 out->append("]", 1); 46 } 47 } 48 49 void JSONCodeTableWriter::JSONEscape(const char* data, 50 size_t size, 51 string* out) { 52 for (size_t i = 0; i < size; ++i) { 53 const char c = data[i]; 54 switch (c) { 55 case '"': out->append("\\\"", 2); break; 56 case '\\': out->append("\\\\", 2); break; 57 case '\b': out->append("\\b", 2); break; 58 case '\f': out->append("\\f", 2); break; 59 case '\n': out->append("\\n", 2); break; 60 case '\r': out->append("\\r", 2); break; 61 case '\t': out->append("\\t", 2); break; 62 default: 63 // encode zero as unicode, also all control codes. 64 if (c < 32 || c >= 127) { 65 char unicode_code[8] = ""; 66 snprintf(unicode_code, sizeof(unicode_code), "\\u%04x", c); 67 out->append(unicode_code, strlen(unicode_code)); 68 } else { 69 out->push_back(c); 70 } 71 } 72 } 73 } 74 75 void JSONCodeTableWriter::Add(const char* data, size_t size) { 76 output_.push_back('\"'); 77 JSONEscape(data, size, &output_); 78 output_.append("\",", 2); 79 target_length_ += size; 80 } 81 82 void JSONCodeTableWriter::Copy(int32_t offset, size_t size) { 83 std::ostringstream copy_code; 84 copy_code << offset << "," << size << ","; 85 output_.append(copy_code.str()); 86 target_length_ += size; 87 } 88 89 void JSONCodeTableWriter::Run(size_t size, unsigned char byte) { 90 output_.push_back('\"'); 91 output_.append(string(size, byte).data(), size); 92 output_.append("\",", 2); 93 target_length_ += size; 94 } 95 96 size_t JSONCodeTableWriter::target_length() const { 97 return target_length_; 98 } 99 100 void JSONCodeTableWriter::WriteHeader(OutputStringInterface *, 101 VCDiffFormatExtensionFlags) { 102 // The JSON format does not need a header. 103 } 104 105 } // namespace open_vcdiff 106