1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 #ifndef TENSORFLOW_TENSORFLOW_LITE_SUPPORT_CODEGEN_UTILS_H_ 16 #define TENSORFLOW_TENSORFLOW_LITE_SUPPORT_CODEGEN_UTILS_H_ 17 18 #include <map> 19 #include <sstream> 20 #include <string> 21 22 namespace tflite { 23 namespace support { 24 namespace codegen { 25 26 /// Collects runtime error logs which could be showed later. 27 // TODO(b/150538286): Consider a better mechanism to simplify callsite code. 28 class ErrorReporter { 29 public: 30 int Warning(const char* format, ...); 31 int Error(const char* format, ...); 32 std::string GetMessage(); 33 34 private: 35 int Report(const char* prefix, const char* format, va_list args); 36 std::stringstream buffer_; 37 }; 38 39 /// Implements basic code generating with text templates. 40 /// 41 /// It could accept code templates and concatenate them into complete codes. A 42 /// template could contain named values. 43 /// 44 /// Example code: 45 /// CodeWriter code; 46 /// code.SetValue("NAME", "Foo"); 47 /// code.Append("void {{NAME}}() { printf("%s", "{{NAME}}"); }"); 48 /// code.SetValue("NAME", "Bar"); 49 /// code.Append("void {{NAME}}() { printf("%s", "{{NAME}}"); }"); 50 /// 51 /// Output: 52 /// void Foo() { printf("%s", "Foo"); } 53 /// void Bar() { printf("%s", "Bar"); } 54 class CodeWriter { 55 public: 56 explicit CodeWriter(ErrorReporter* err); 57 /// Sets value to a token. When generating code with template, a string in a 58 /// pair of {{ and }} will be regarded as a token and replaced with the 59 /// corresponding value in code generation. 60 /// It rewrites if the token already has a value. 61 void SetTokenValue(const std::string& token, const std::string& value); 62 63 /// Gets the current value set on the given token. 64 const std::string GetTokenValue(const std::string& token) const; 65 66 /// Sets the unit indent string. For example, in Java it should be " ". 67 void SetIndentString(const std::string& indent); 68 69 /// Increases the indent by a unit (the string set in SetIndentString). 70 void Indent(); 71 72 /// Decreases the indent by a unit (the string set in SetIndentString). 73 void Outdent(); 74 75 /// Generates the indentation string. 76 std::string GenerateIndent() const; 77 78 /// Appends a piece of template codes to the stream. Every named value will be 79 /// replaced via the real value. A new line will always be appended at the 80 /// end. 81 void Append(const std::string& text); 82 83 /// Appends a piece of template codes to the stream. Same with `Append`, but a 84 /// new line will not be appended at the end. 85 void AppendNoNewLine(const std::string& text); 86 87 /// Appends a new line to the stream. 88 void NewLine(); 89 90 /// Deletes the last N charaters in the stream. If the stream has less than N 91 /// characters, deletes all. 92 void Backspace(int n); 93 94 std::string ToString() const; 95 96 /// Checks if the internal string stream is empty. Note: This method has 97 // overhead. 98 bool IsStreamEmpty() const; 99 100 /// Clears all the internal string stream and value map. 101 void Clear(); 102 103 private: 104 void AppendInternal(const std::string& text, bool newline); 105 106 std::string indent_str_; 107 int indent_; 108 109 std::map<std::string, std::string> value_map_; 110 std::string buffer_; 111 112 ErrorReporter* err_; 113 }; 114 115 /// Converts foo_bar_name to fooBarName. It's callers duty to make sure given 116 /// string "s" is already in snake case; or unexpected behavior may occur. 117 std::string SnakeCaseToCamelCase(const std::string& s); 118 119 /// Joins 2 parts of file path into one, connected by unix path seperator '/'. 120 /// It's callers duty to ensure the two parts are valid. 121 std::string JoinPath(const std::string& a, const std::string& b); 122 123 } // namespace codegen 124 } // namespace support 125 } // namespace tflite 126 127 #endif // TENSORFLOW_TENSORFLOW_LITE_SUPPORT_CODEGEN_UTILS_H_ 128