aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/core/lib/strings/proto_text_util.h
diff options
context:
space:
mode:
authorGravatar A. Unique TensorFlower <nobody@tensorflow.org>2016-04-14 19:15:20 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2016-04-14 20:22:35 -0700
commitdf15baa9b10a0b2d194181dff7ee14bff70d9b8f (patch)
treea66e1fcb309a7404a2749140d8bac991a6524ac0 /tensorflow/core/lib/strings/proto_text_util.h
parent104fe2822b419c4154d11c401ffd4a3a6e8f24c6 (diff)
Add tools/proto_text for generating ProtoDebugString,
ProtoShortDebugString, and ProtoParseFromString methods from protos. This will allow changing code used on mobile to use the proto LITE_RUNTIME, to reduce code size. This change is only for the tool itself. A future change will add a better genrule and use it the generated code in tensorflow. Change: 119919087
Diffstat (limited to 'tensorflow/core/lib/strings/proto_text_util.h')
-rw-r--r--tensorflow/core/lib/strings/proto_text_util.h191
1 files changed, 191 insertions, 0 deletions
diff --git a/tensorflow/core/lib/strings/proto_text_util.h b/tensorflow/core/lib/strings/proto_text_util.h
new file mode 100644
index 0000000000..35040a9408
--- /dev/null
+++ b/tensorflow/core/lib/strings/proto_text_util.h
@@ -0,0 +1,191 @@
+/* Copyright 2016 Google Inc. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#ifndef THIRD_PARTY_TENSORFLOW_CORE_LIB_STRINGS_PROTO_TEXT_UTIL_H_
+#define THIRD_PARTY_TENSORFLOW_CORE_LIB_STRINGS_PROTO_TEXT_UTIL_H_
+
+#include "tensorflow/core/lib/strings/numbers.h"
+#include "tensorflow/core/lib/strings/scanner.h"
+#include "tensorflow/core/lib/strings/str_util.h"
+#include "tensorflow/core/lib/strings/strcat.h"
+#include "tensorflow/core/platform/macros.h"
+#include "tensorflow/core/platform/protobuf.h"
+
+namespace tensorflow {
+namespace strings {
+
+static constexpr char kColonSeparator[] = ": ";
+
+// Helper functions for writing proto-text output.
+// Used by the code generated from tools/proto_text/gen_proto_text_lib.cc.
+class ProtoTextOutput {
+ public:
+ // Construct a ProtoTextOutput that writes to <output> If short_debug is true,
+ // outputs text to match proto.ShortDebugString(); else matches
+ // proto.DebugString().
+ ProtoTextOutput(string* output, bool short_debug)
+ : output_(output),
+ short_debug_(short_debug),
+ field_separator_(short_debug ? " " : "\n") {}
+
+ // Writes opening of nested message and increases indent level.
+ void OpenNestedMessage(const char field_name[]) {
+ StrAppend(output_, level_empty_ ? "" : field_separator_, indent_,
+ field_name, " {", field_separator_);
+ if (!short_debug_) StrAppend(&indent_, " ");
+ level_empty_ = true;
+ }
+
+ // Writes close of nested message and decreases indent level.
+ void CloseNestedMessage() {
+ if (!short_debug_) indent_.resize(indent_.size() - 2);
+ StrAppend(output_, level_empty_ ? "" : field_separator_, indent_, "}");
+ level_empty_ = false;
+ }
+
+ // Print the close of the top-level message that was printed.
+ void CloseTopMessage() {
+ if (!short_debug_ && !level_empty_) StrAppend(output_, "\n");
+ }
+
+ // Appends a numeric value, like my_field: 123
+ template <typename T>
+ void AppendNumeric(const char field_name[], T value) {
+ AppendFieldAndValue(field_name, StrCat(value));
+ }
+
+ // Appends a numeric value, like my_field: 123, but only if value != 0.
+ template <typename T>
+ void AppendNumericIfNotZero(const char field_name[], T value) {
+ if (value != 0) AppendNumeric(field_name, value);
+ }
+
+ // Appends a bool value, either my_field: true or my_field: false.
+ void AppendBool(const char field_name[], bool value) {
+ AppendFieldAndValue(field_name, value ? "true" : "false");
+ }
+
+ // Appends a bool value, as my_field: true, only if value is true.
+ void AppendBoolIfTrue(const char field_name[], bool value) {
+ if (value) AppendBool(field_name, value);
+ }
+
+ // Appends a string value, like my_field: "abc123".
+ void AppendString(const char field_name[], const string& value) {
+ AppendFieldAndValue(
+ field_name, StrCat("\"", ::tensorflow::str_util::CEscape(value), "\""));
+ }
+
+ // Appends a string value, like my_field: "abc123", but only if value is not
+ // empty.
+ void AppendStringIfNotEmpty(const char field_name[], const string& value) {
+ if (!value.empty()) AppendString(field_name, value);
+ }
+
+ // Appends the string name of an enum, like my_field: FIRST_ENUM.
+ void AppendEnumName(const char field_name[], const string& name) {
+ AppendFieldAndValue(field_name, name);
+ }
+
+ private:
+ void AppendFieldAndValue(const char field_name[], const string& value_text) {
+ StrAppend(output_, level_empty_ ? "" : field_separator_, indent_,
+ field_name, kColonSeparator, value_text);
+ level_empty_ = false;
+ }
+
+ string* const output_;
+ const bool short_debug_;
+ const string field_separator_;
+ string indent_;
+
+ // False when at least one field has been output for the message at the
+ // current deepest level of nesting.
+ bool level_empty_ = true;
+
+ TF_DISALLOW_COPY_AND_ASSIGN(ProtoTextOutput);
+};
+
+inline bool ProtoParseNumeric(StringPiece s, int32* value) {
+ return ::tensorflow::strings::safe_strto32(s, value);
+}
+
+inline bool ProtoParseNumeric(StringPiece s, uint32* value) {
+ return ::tensorflow::strings::safe_strtou32(s, value);
+}
+
+inline bool ProtoParseNumeric(StringPiece s, int64* value) {
+ return ::tensorflow::strings::safe_strto64(s, value);
+}
+
+inline bool ProtoParseNumeric(StringPiece s, uint64* value) {
+ return ::tensorflow::strings::safe_strtou64(s, value);
+}
+
+inline bool ProtoParseNumeric(StringPiece s, float* value) {
+ return ::tensorflow::strings::safe_strtof(s.ToString().c_str(), value);
+}
+
+inline bool ProtoParseNumeric(StringPiece s, double* value) {
+ return ::tensorflow::strings::safe_strtod(s.ToString().c_str(), value);
+}
+
+inline void ProtoSpaceAndComments(Scanner* scanner) {
+ for (;;) {
+ scanner->AnySpace();
+ if (scanner->Peek() != '#') return;
+ // Skip until newline.
+ while (scanner->Peek('\n') != '\n') scanner->One(Scanner::ALL);
+ }
+}
+
+// Parse the next numeric value from <scanner>, returning false if parsing
+// failed.
+template <typename T>
+bool ProtoParseNumericFromScanner(Scanner* scanner, T* value) {
+ StringPiece numeric_str;
+ scanner->RestartCapture();
+ if (!scanner->Many(Scanner::LETTER_DIGIT_DOT_PLUS_MINUS)
+ .GetResult(nullptr, &numeric_str)) {
+ return false;
+ }
+
+ // Special case to disallow multiple leading zeroes, to match proto parsing.
+ int leading_zero = 0;
+ for (int i = 0; i < numeric_str.size(); ++i) {
+ const char ch = numeric_str[i];
+ if (ch == '0') {
+ if (++leading_zero > 1) return false;
+ } else if (ch != '-') {
+ break;
+ }
+ }
+
+ ProtoSpaceAndComments(scanner);
+ return ProtoParseNumeric(numeric_str, value);
+}
+
+// Parse the next boolean value from <scanner>, returning false if parsing
+// failed.
+bool ProtoParseBoolFromScanner(Scanner* scanner, bool* value);
+
+// Parse the next string literal from <scanner>, returning false if parsing
+// failed.
+bool ProtoParseStringLiteralFromScanner(Scanner* scanner, string* value);
+
+} // namespace strings
+} // namespace tensorflow
+
+#endif // THIRD_PARTY_TENSORFLOW_CORE_LIB_STRINGS_PROTO_TEXT_UTIL_H_