parent
16c9b4691d
commit
5ace0e8450
12 changed files with 700 additions and 488 deletions
@ -0,0 +1,263 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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 Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
// OWNER 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 "google/protobuf/compiler/objectivec/import_writer.h" |
||||
#include "google/protobuf/compiler/objectivec/names.h" |
||||
#include "google/protobuf/io/printer.h" |
||||
|
||||
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
|
||||
// error cases, so it seems to be ok to use as a back door for errors.
|
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
namespace objectivec { |
||||
|
||||
namespace { |
||||
|
||||
class ProtoFrameworkCollector : public LineConsumer { |
||||
public: |
||||
ProtoFrameworkCollector(std::map<std::string, std::string>* inout_proto_file_to_framework_name) |
||||
: map_(inout_proto_file_to_framework_name) {} |
||||
|
||||
virtual bool ConsumeLine(const absl::string_view& line, std::string* out_error) override; |
||||
|
||||
private: |
||||
std::map<std::string, std::string>* map_; |
||||
}; |
||||
|
||||
bool ProtoFrameworkCollector::ConsumeLine( |
||||
const absl::string_view& line, std::string* out_error) { |
||||
int offset = line.find(':'); |
||||
if (offset == absl::string_view::npos) { |
||||
*out_error = |
||||
std::string("Framework/proto file mapping line without colon sign: '") + |
||||
std::string(line) + "'."; |
||||
return false; |
||||
} |
||||
absl::string_view framework_name = line.substr(0, offset); |
||||
absl::string_view proto_file_list = line.substr(offset + 1); |
||||
TrimWhitespace(&framework_name); |
||||
|
||||
int start = 0; |
||||
while (start < proto_file_list.length()) { |
||||
offset = proto_file_list.find(',', start); |
||||
if (offset == absl::string_view::npos) { |
||||
offset = proto_file_list.length(); |
||||
} |
||||
|
||||
absl::string_view proto_file = proto_file_list.substr(start, offset - start); |
||||
TrimWhitespace(&proto_file); |
||||
if (!proto_file.empty()) { |
||||
std::map<std::string, std::string>::iterator existing_entry = |
||||
map_->find(std::string(proto_file)); |
||||
if (existing_entry != map_->end()) { |
||||
std::cerr << "warning: duplicate proto file reference, replacing " |
||||
"framework entry for '" |
||||
<< std::string(proto_file) << "' with '" << std::string(framework_name) |
||||
<< "' (was '" << existing_entry->second << "')." << std::endl; |
||||
std::cerr.flush(); |
||||
} |
||||
|
||||
if (proto_file.find(' ') != absl::string_view::npos) { |
||||
std::cerr << "note: framework mapping file had a proto file with a " |
||||
"space in, hopefully that isn't a missing comma: '" |
||||
<< std::string(proto_file) << "'" << std::endl; |
||||
std::cerr.flush(); |
||||
} |
||||
|
||||
(*map_)[std::string(proto_file)] = std::string(framework_name); |
||||
} |
||||
|
||||
start = offset + 1; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
ImportWriter::ImportWriter( |
||||
const std::string& generate_for_named_framework, |
||||
const std::string& named_framework_to_proto_path_mappings_path, |
||||
const std::string& runtime_import_prefix, bool include_wkt_imports) |
||||
: generate_for_named_framework_(generate_for_named_framework), |
||||
named_framework_to_proto_path_mappings_path_( |
||||
named_framework_to_proto_path_mappings_path), |
||||
runtime_import_prefix_(runtime_import_prefix), |
||||
include_wkt_imports_(include_wkt_imports), |
||||
need_to_parse_mapping_file_(true) {} |
||||
|
||||
ImportWriter::~ImportWriter() {} |
||||
|
||||
void ImportWriter::AddFile(const FileDescriptor* file, |
||||
const std::string& header_extension) { |
||||
if (IsProtobufLibraryBundledProtoFile(file)) { |
||||
// The imports of the WKTs are only needed within the library itself,
|
||||
// in other cases, they get skipped because the generated code already
|
||||
// import GPBProtocolBuffers.h and hence proves them.
|
||||
if (include_wkt_imports_) { |
||||
const std::string header_name = |
||||
"GPB" + FilePathBasename(file) + header_extension; |
||||
protobuf_imports_.push_back(header_name); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
// Lazy parse any mappings.
|
||||
if (need_to_parse_mapping_file_) { |
||||
ParseFrameworkMappings(); |
||||
} |
||||
|
||||
std::map<std::string, std::string>::iterator proto_lookup = |
||||
proto_file_to_framework_name_.find(file->name()); |
||||
if (proto_lookup != proto_file_to_framework_name_.end()) { |
||||
other_framework_imports_.push_back( |
||||
proto_lookup->second + "/" + |
||||
FilePathBasename(file) + header_extension); |
||||
return; |
||||
} |
||||
|
||||
if (!generate_for_named_framework_.empty()) { |
||||
other_framework_imports_.push_back( |
||||
generate_for_named_framework_ + "/" + |
||||
FilePathBasename(file) + header_extension); |
||||
return; |
||||
} |
||||
|
||||
other_imports_.push_back(FilePath(file) + header_extension); |
||||
} |
||||
|
||||
void ImportWriter::Print(io::Printer* printer) const { |
||||
bool add_blank_line = false; |
||||
|
||||
if (!protobuf_imports_.empty()) { |
||||
PrintRuntimeImports(printer, protobuf_imports_, runtime_import_prefix_); |
||||
add_blank_line = true; |
||||
} |
||||
|
||||
if (!other_framework_imports_.empty()) { |
||||
if (add_blank_line) { |
||||
printer->Print("\n"); |
||||
} |
||||
|
||||
for (std::vector<std::string>::const_iterator iter = |
||||
other_framework_imports_.begin(); |
||||
iter != other_framework_imports_.end(); ++iter) { |
||||
printer->Print( |
||||
"#import <$header$>\n", |
||||
"header", *iter); |
||||
} |
||||
|
||||
add_blank_line = true; |
||||
} |
||||
|
||||
if (!other_imports_.empty()) { |
||||
if (add_blank_line) { |
||||
printer->Print("\n"); |
||||
} |
||||
|
||||
for (std::vector<std::string>::const_iterator iter = other_imports_.begin(); |
||||
iter != other_imports_.end(); ++iter) { |
||||
printer->Print( |
||||
"#import \"$header$\"\n", |
||||
"header", *iter); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void ImportWriter::PrintRuntimeImports( |
||||
io::Printer* printer, const std::vector<std::string>& header_to_import, |
||||
const std::string& runtime_import_prefix, bool default_cpp_symbol) { |
||||
// Given an override, use that.
|
||||
if (!runtime_import_prefix.empty()) { |
||||
for (const auto& header : header_to_import) { |
||||
printer->Print( |
||||
" #import \"$import_prefix$/$header$\"\n", |
||||
"import_prefix", runtime_import_prefix, |
||||
"header", header); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
const std::string framework_name(ProtobufLibraryFrameworkName); |
||||
const std::string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); |
||||
|
||||
if (default_cpp_symbol) { |
||||
printer->Print( |
||||
"// This CPP symbol can be defined to use imports that match up to the framework\n" |
||||
"// imports needed when using CocoaPods.\n" |
||||
"#if !defined($cpp_symbol$)\n" |
||||
" #define $cpp_symbol$ 0\n" |
||||
"#endif\n" |
||||
"\n", |
||||
"cpp_symbol", cpp_symbol); |
||||
} |
||||
|
||||
printer->Print( |
||||
"#if $cpp_symbol$\n", |
||||
"cpp_symbol", cpp_symbol); |
||||
for (const auto& header : header_to_import) { |
||||
printer->Print( |
||||
" #import <$framework_name$/$header$>\n", |
||||
"framework_name", framework_name, |
||||
"header", header); |
||||
} |
||||
printer->Print( |
||||
"#else\n"); |
||||
for (const auto& header : header_to_import) { |
||||
printer->Print( |
||||
" #import \"$header$\"\n", |
||||
"header", header); |
||||
} |
||||
printer->Print( |
||||
"#endif\n"); |
||||
} |
||||
|
||||
void ImportWriter::ParseFrameworkMappings() { |
||||
need_to_parse_mapping_file_ = false; |
||||
if (named_framework_to_proto_path_mappings_path_.empty()) { |
||||
return; // Nothing to do.
|
||||
} |
||||
|
||||
ProtoFrameworkCollector collector(&proto_file_to_framework_name_); |
||||
std::string parse_error; |
||||
if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_, |
||||
&collector, &parse_error)) { |
||||
std::cerr << "error parsing " << named_framework_to_proto_path_mappings_path_ |
||||
<< " : " << parse_error << std::endl; |
||||
std::cerr.flush(); |
||||
} |
||||
} |
||||
|
||||
} // namespace objectivec
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,84 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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 Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
// OWNER 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_IMPORT_WRITER_H__ |
||||
#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_IMPORT_WRITER_H__ |
||||
|
||||
#include <string> |
||||
#include <vector> |
||||
|
||||
#include "google/protobuf/descriptor.h" |
||||
#include "google/protobuf/descriptor.pb.h" |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
namespace objectivec { |
||||
|
||||
// Helper class for parsing framework import mappings and generating
|
||||
// import statements.
|
||||
class ImportWriter { |
||||
public: |
||||
ImportWriter(const std::string& generate_for_named_framework, |
||||
const std::string& named_framework_to_proto_path_mappings_path, |
||||
const std::string& runtime_import_prefix, |
||||
bool include_wkt_imports); |
||||
~ImportWriter(); |
||||
|
||||
void AddFile(const FileDescriptor* file, const std::string& header_extension); |
||||
void Print(io::Printer* printer) const; |
||||
|
||||
static void PrintRuntimeImports(io::Printer* printer, |
||||
const std::vector<std::string>& header_to_import, |
||||
const std::string& runtime_import_prefix, |
||||
bool default_cpp_symbol = false); |
||||
|
||||
private: |
||||
void ParseFrameworkMappings(); |
||||
|
||||
const std::string generate_for_named_framework_; |
||||
const std::string named_framework_to_proto_path_mappings_path_; |
||||
const std::string runtime_import_prefix_; |
||||
const bool include_wkt_imports_; |
||||
std::map<std::string, std::string> proto_file_to_framework_name_; |
||||
bool need_to_parse_mapping_file_; |
||||
|
||||
std::vector<std::string> protobuf_imports_; |
||||
std::vector<std::string> other_framework_imports_; |
||||
std::vector<std::string> other_imports_; |
||||
}; |
||||
|
||||
|
||||
} // namespace objectivec
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_IMPORT_WRITER_H__
|
@ -0,0 +1,267 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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 Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
// OWNER 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 "google/protobuf/compiler/code_generator.h" |
||||
#include "google/protobuf/stubs/strutil.h" |
||||
#include "absl/strings/ascii.h" |
||||
#include "absl/strings/escaping.h" |
||||
#include "absl/strings/str_replace.h" |
||||
#include "absl/strings/str_split.h" |
||||
#include "google/protobuf/compiler/objectivec/text_format_decode_data.h" |
||||
#include "google/protobuf/compiler/objectivec/names.h" |
||||
#include "google/protobuf/io/coded_stream.h" |
||||
#include "google/protobuf/io/printer.h" |
||||
#include "google/protobuf/io/zero_copy_stream_impl.h" |
||||
|
||||
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
|
||||
// error cases, so it seems to be ok to use as a back door for errors.
|
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
namespace objectivec { |
||||
|
||||
namespace { |
||||
|
||||
// Helper to build up the decode data for a string.
|
||||
class DecodeDataBuilder { |
||||
public: |
||||
DecodeDataBuilder() { Reset(); } |
||||
|
||||
bool AddCharacter(const char desired, const char input); |
||||
void AddUnderscore() { |
||||
Push(); |
||||
need_underscore_ = true; |
||||
} |
||||
std::string Finish() { |
||||
Push(); |
||||
return decode_data_; |
||||
} |
||||
|
||||
private: |
||||
static constexpr uint8_t kAddUnderscore = 0x80; |
||||
|
||||
static constexpr uint8_t kOpAsIs = 0x00; |
||||
static constexpr uint8_t kOpFirstUpper = 0x40; |
||||
static constexpr uint8_t kOpFirstLower = 0x20; |
||||
static constexpr uint8_t kOpAllUpper = 0x60; |
||||
|
||||
static constexpr int kMaxSegmentLen = 0x1f; |
||||
|
||||
void AddChar(const char desired) { |
||||
++segment_len_; |
||||
is_all_upper_ &= absl::ascii_isupper(desired); |
||||
} |
||||
|
||||
void Push() { |
||||
uint8_t op = (op_ | segment_len_); |
||||
if (need_underscore_) op |= kAddUnderscore; |
||||
if (op != 0) { |
||||
decode_data_ += (char)op; |
||||
} |
||||
Reset(); |
||||
} |
||||
|
||||
bool AddFirst(const char desired, const char input) { |
||||
if (desired == input) { |
||||
op_ = kOpAsIs; |
||||
} else if (desired == absl::ascii_toupper(input)) { |
||||
op_ = kOpFirstUpper; |
||||
} else if (desired == absl::ascii_tolower(input)) { |
||||
op_ = kOpFirstLower; |
||||
} else { |
||||
// Can't be transformed to match.
|
||||
return false; |
||||
} |
||||
AddChar(desired); |
||||
return true; |
||||
} |
||||
|
||||
void Reset() { |
||||
need_underscore_ = false; |
||||
op_ = 0; |
||||
segment_len_ = 0; |
||||
is_all_upper_ = true; |
||||
} |
||||
|
||||
bool need_underscore_; |
||||
bool is_all_upper_; |
||||
uint8_t op_; |
||||
int segment_len_; |
||||
|
||||
std::string decode_data_; |
||||
}; |
||||
|
||||
bool DecodeDataBuilder::AddCharacter(const char desired, const char input) { |
||||
// If we've hit the max size, push to start a new segment.
|
||||
if (segment_len_ == kMaxSegmentLen) { |
||||
Push(); |
||||
} |
||||
if (segment_len_ == 0) { |
||||
return AddFirst(desired, input); |
||||
} |
||||
|
||||
// Desired and input match...
|
||||
if (desired == input) { |
||||
// If we aren't transforming it, or we're upper casing it and it is
|
||||
// supposed to be uppercase; just add it to the segment.
|
||||
if ((op_ != kOpAllUpper) || absl::ascii_isupper(desired)) { |
||||
AddChar(desired); |
||||
return true; |
||||
} |
||||
|
||||
// Add the current segment, and start the next one.
|
||||
Push(); |
||||
return AddFirst(desired, input); |
||||
} |
||||
|
||||
// If we need to uppercase, and everything so far has been uppercase,
|
||||
// promote op to AllUpper.
|
||||
if ((desired == absl::ascii_toupper(input)) && is_all_upper_) { |
||||
op_ = kOpAllUpper; |
||||
AddChar(desired); |
||||
return true; |
||||
} |
||||
|
||||
// Give up, push and start a new segment.
|
||||
Push(); |
||||
return AddFirst(desired, input); |
||||
} |
||||
|
||||
// If decode data can't be generated, a directive for the raw string
|
||||
// is used instead.
|
||||
std::string DirectDecodeString(const std::string& str) { |
||||
std::string result; |
||||
result += (char)'\0'; // Marker for full string.
|
||||
result += str; |
||||
result += (char)'\0'; // End of string.
|
||||
return result; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
TextFormatDecodeData::TextFormatDecodeData() { } |
||||
|
||||
TextFormatDecodeData::~TextFormatDecodeData() { } |
||||
|
||||
void TextFormatDecodeData::AddString(int32_t key, |
||||
const std::string& input_for_decode, |
||||
const std::string& desired_output) { |
||||
for (std::vector<DataEntry>::const_iterator i = entries_.begin(); |
||||
i != entries_.end(); ++i) { |
||||
if (i->first == key) { |
||||
std::cerr << "error: duplicate key (" << key |
||||
<< ") making TextFormat data, input: \"" << input_for_decode |
||||
<< "\", desired: \"" << desired_output << "\"." << std::endl; |
||||
std::cerr.flush(); |
||||
abort(); |
||||
} |
||||
} |
||||
|
||||
const std::string& data = TextFormatDecodeData::DecodeDataForString( |
||||
input_for_decode, desired_output); |
||||
entries_.push_back(DataEntry(key, data)); |
||||
} |
||||
|
||||
std::string TextFormatDecodeData::Data() const { |
||||
std::ostringstream data_stringstream; |
||||
|
||||
if (num_entries() > 0) { |
||||
io::OstreamOutputStream data_outputstream(&data_stringstream); |
||||
io::CodedOutputStream output_stream(&data_outputstream); |
||||
|
||||
output_stream.WriteVarint32(num_entries()); |
||||
for (std::vector<DataEntry>::const_iterator i = entries_.begin(); |
||||
i != entries_.end(); ++i) { |
||||
output_stream.WriteVarint32(i->first); |
||||
output_stream.WriteString(i->second); |
||||
} |
||||
} |
||||
|
||||
data_stringstream.flush(); |
||||
return data_stringstream.str(); |
||||
} |
||||
|
||||
// static
|
||||
std::string TextFormatDecodeData::DecodeDataForString( |
||||
const std::string& input_for_decode, const std::string& desired_output) { |
||||
if (input_for_decode.empty() || desired_output.empty()) { |
||||
std::cerr << "error: got empty string for making TextFormat data, input: \"" |
||||
<< input_for_decode << "\", desired: \"" << desired_output << "\"." |
||||
<< std::endl; |
||||
std::cerr.flush(); |
||||
abort(); |
||||
} |
||||
if ((input_for_decode.find('\0') != std::string::npos) || |
||||
(desired_output.find('\0') != std::string::npos)) { |
||||
std::cerr << "error: got a null char in a string for making TextFormat data," |
||||
<< " input: \"" << absl::CEscape(input_for_decode) << "\", desired: \"" |
||||
<< absl::CEscape(desired_output) << "\"." << std::endl; |
||||
std::cerr.flush(); |
||||
abort(); |
||||
} |
||||
|
||||
DecodeDataBuilder builder; |
||||
|
||||
// Walk the output building it from the input.
|
||||
int x = 0; |
||||
for (int y = 0; y < desired_output.size(); y++) { |
||||
const char d = desired_output[y]; |
||||
if (d == '_') { |
||||
builder.AddUnderscore(); |
||||
continue; |
||||
} |
||||
|
||||
if (x >= input_for_decode.size()) { |
||||
// Out of input, no way to encode it, just return a full decode.
|
||||
return DirectDecodeString(desired_output); |
||||
} |
||||
if (builder.AddCharacter(d, input_for_decode[x])) { |
||||
++x; // Consumed one input
|
||||
} else { |
||||
// Couldn't transform for the next character, just return a full decode.
|
||||
return DirectDecodeString(desired_output); |
||||
} |
||||
} |
||||
|
||||
if (x != input_for_decode.size()) { |
||||
// Extra input (suffix from name sanitizing?), just return a full decode.
|
||||
return DirectDecodeString(desired_output); |
||||
} |
||||
|
||||
// Add the end marker.
|
||||
return builder.Finish() + (char)'\0'; |
||||
} |
||||
|
||||
|
||||
} // namespace objectivec
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -0,0 +1,71 @@ |
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// 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 Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
// OWNER 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.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__ |
||||
#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__ |
||||
|
||||
#include <string> |
||||
#include <vector> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
namespace compiler { |
||||
namespace objectivec { |
||||
|
||||
// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
|
||||
// the input into the expected output.
|
||||
class TextFormatDecodeData { |
||||
public: |
||||
TextFormatDecodeData(); |
||||
~TextFormatDecodeData(); |
||||
|
||||
TextFormatDecodeData(const TextFormatDecodeData&) = delete; |
||||
TextFormatDecodeData& operator=(const TextFormatDecodeData&) = delete; |
||||
|
||||
void AddString(int32_t key, const std::string& input_for_decode, |
||||
const std::string& desired_output); |
||||
size_t num_entries() const { return entries_.size(); } |
||||
std::string Data() const; |
||||
|
||||
static std::string DecodeDataForString(const std::string& input_for_decode, |
||||
const std::string& desired_output); |
||||
|
||||
private: |
||||
typedef std::pair<int32_t, std::string> DataEntry; |
||||
std::vector<DataEntry> entries_; |
||||
}; |
||||
|
||||
|
||||
} // namespace objectivec
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__
|
Loading…
Reference in new issue