File ola-remove_defines.patch of Package ola
diff -urN ola-0.10.7/protoc/CppFileGenerator.cpp ola-0.10.7-devel/protoc/CppFileGenerator.cpp
--- ola-0.10.7/protoc/CppFileGenerator.cpp 2016-12-12 01:00:42.000000000 +0200
+++ ola-0.10.7-devel/protoc/CppFileGenerator.cpp 2019-11-22 13:25:13.343098041 +0200
@@ -231,9 +231,9 @@
printer->Print(
"namespace {\n"
"\n"
- "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
+ "::google::protobuf::internal::once_flag protobuf_AssignDescriptors_once_;\n"
"inline void protobuf_AssignDescriptorsOnce() {\n"
- " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,"
+ " ::google::protobuf::internal::call_once(protobuf_AssignDescriptors_once_,"
"\n"
" &$assigndescriptorsname$);\n"
"}\n"
diff -urN ola-0.10.7/protoc/CppFileGenerator.cpp.orig ola-0.10.7-devel/protoc/CppFileGenerator.cpp.orig
--- ola-0.10.7/protoc/CppFileGenerator.cpp.orig 1970-01-01 02:00:00.000000000 +0200
+++ ola-0.10.7-devel/protoc/CppFileGenerator.cpp.orig 2016-12-12 01:00:42.000000000 +0200
@@ -0,0 +1,263 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// Edited by Simon Newton for OLA
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/printer.h>
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "protoc/CppFileGenerator.h"
+#include "protoc/GeneratorHelpers.h"
+#include "protoc/ServiceGenerator.h"
+#include "protoc/StrUtil.h"
+
+namespace ola {
+
+using google::protobuf::FileDescriptor;
+using google::protobuf::ServiceDescriptor;
+using google::protobuf::io::Printer;
+using std::auto_ptr;
+using std::string;
+
+
+FileGenerator::FileGenerator(const FileDescriptor *file,
+ const string &output_name)
+ : m_file(file),
+ m_output_name(output_name) {
+ SplitStringUsing(file->package(), ".", &package_parts_);
+
+ ServiceGenerator::Options options;
+ for (int i = 0; i < file->service_count(); i++) {
+ m_service_generators.push_back(
+ new ServiceGenerator(file->service(i), options));
+ }
+}
+
+FileGenerator::~FileGenerator() {
+ ServiceGenerators::iterator iter = m_service_generators.begin();
+ for (; iter != m_service_generators.end(); ++iter) {
+ delete *iter;
+ }
+}
+
+void FileGenerator::GenerateHeader(Printer *printer) {
+ const string filename_identifier = FilenameIdentifier(m_output_name);
+
+ std::map<string, string> var_map;
+ var_map["basename"] = StripProto(m_file->name());
+ var_map["filename"] = m_file->name();
+ var_map["filename_identifier"] = filename_identifier;
+
+ // Generate top of header.
+ printer->Print(
+ var_map,
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n"
+ "#ifndef PROTOBUF_$filename_identifier$__INCLUDED "
+ "// NOLINT(build/header_guard)\n"
+ "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
+ "\n"
+ "#include <google/protobuf/service.h>\n"
+ "\n"
+ "#include \"$basename$.pb.h\"\n"
+ "#include \"common/rpc/RpcService.h\"\n"
+ "\n"
+ "namespace ola {\n"
+ "namespace rpc {\n"
+ "class RpcController;\n"
+ "class RpcChannel;\n"
+ "} // rpc\n"
+ "} // ola\n"
+ "\n");
+
+ GenerateNamespaceOpeners(printer);
+
+ ServiceGenerators::iterator iter = m_service_generators.begin();
+ for (; iter != m_service_generators.end(); ++iter) {
+ (*iter)->GenerateDeclarations(printer);
+ }
+
+ GenerateNamespaceClosers(printer);
+
+ printer->Print(
+ "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
+ "filename_identifier", filename_identifier);
+}
+
+
+void FileGenerator::GenerateImplementation(Printer *printer) {
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n"
+ // TODO(Peter): This should be a full path to remove the lint error
+ "#include \"$file$.pb.h\"\n"
+ "\n"
+ "#include <google/protobuf/descriptor.h> // NOLINT(build/include)\n"
+ "#include <google/protobuf/stubs/once.h>\n"
+ "\n"
+ "#include \"common/rpc/RpcChannel.h\"\n"
+ "#include \"common/rpc/RpcController.h\"\n"
+ "\n",
+ "file", m_output_name,
+ "filename", m_file->name());
+
+ GenerateNamespaceOpeners(printer);
+
+ printer->Print(
+ "\n"
+ "namespace {\n"
+ "\n");
+ for (int i = 0; i < m_file->service_count(); i++) {
+ printer->Print(
+ "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ =\n"
+ " NULL;\n",
+ "name", m_file->service(i)->name());
+ }
+ printer->Print(
+ "\n"
+ "} // namespace\n"
+ "\n");
+
+
+ // Define our externally-visible BuildDescriptors() function. (For the lite
+ // library, all this does is initialize default instances.)
+ GenerateBuildDescriptors(printer);
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+
+ ServiceGenerators::iterator iter = m_service_generators.begin();
+ for (; iter != m_service_generators.end(); ++iter) {
+ (*iter)->GenerateImplementation(printer);
+ }
+
+ GenerateNamespaceClosers(printer);
+}
+
+void FileGenerator::GenerateBuildDescriptors(Printer* printer) {
+ // AddDescriptors() is a file-level procedure which adds the encoded
+ // FileDescriptorProto for this .proto file to the global DescriptorPool for
+ // generated files (DescriptorPool::generated_pool()). It either runs at
+ // static initialization time (by default) or when default_instance() is
+ // called for the first time (in LITE_RUNTIME mode with
+ // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
+ // constructs default instances and registers extensions.
+ //
+ // Its sibling, AssignDescriptors(), actually pulls the compiled
+ // FileDescriptor from the DescriptorPool and uses it to populate all of
+ // the global variables which store pointers to the descriptor objects.
+ // It also constructs the reflection objects. It is called the first time
+ // anyone calls descriptor() or GetReflection() on one of the types defined
+ // in the file.
+
+ // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
+ // and we only use AddDescriptors() to allocate default instances.
+ if (HasDescriptorMethods(m_file)) {
+ printer->Print(
+ "\n"
+ "void $assigndescriptorsname$() {\n",
+ "assigndescriptorsname", GlobalAssignDescriptorsName(m_output_name));
+ printer->Indent();
+
+ // Make sure the file has found its way into the pool. If a descriptor
+ // is requested *during* static init then AddDescriptors() may not have
+ // been called yet, so we call it manually. Note that it's fine if
+ // AddDescriptors() is called multiple times.
+ printer->Print(
+ "$adddescriptorsname$();\n",
+ "adddescriptorsname", GlobalAddDescriptorsName(m_file->name()));
+
+ // Get the file's descriptor from the pool.
+ printer->Print(
+ "const ::google::protobuf::FileDescriptor* file =\n"
+ " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName("
+ "\n"
+ " \"$filename$\");\n"
+ // Note that this GOOGLE_CHECK is necessary to prevent a warning about
+ // "file" being unused when compiling an empty .proto file.
+ "GOOGLE_CHECK(file != NULL);\n",
+ "filename", m_file->name());
+
+ for (int i = 0; i < m_file->service_count(); i++) {
+ m_service_generators[i]->GenerateDescriptorInitializer(printer, i);
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+ // ---------------------------------------------------------------
+
+ // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
+ // AssignDescriptors(). All later times, waits for the first call to
+ // complete and then returns.
+ printer->Print(
+ "namespace {\n"
+ "\n"
+ "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
+ "inline void protobuf_AssignDescriptorsOnce() {\n"
+ " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,"
+ "\n"
+ " &$assigndescriptorsname$);\n"
+ "}\n"
+ "\n",
+ "assigndescriptorsname", GlobalAssignDescriptorsName(m_output_name));
+
+ printer->Print("} // namespace\n");
+ }
+}
+
+void FileGenerator::GenerateNamespaceOpeners(Printer* printer) {
+ if (package_parts_.size() > 0) printer->Print("\n");
+
+ for (unsigned int i = 0; i < package_parts_.size(); i++) {
+ printer->Print("namespace $part$ {\n", "part", package_parts_[i]);
+ }
+}
+
+void FileGenerator::GenerateNamespaceClosers(Printer* printer) {
+ if (package_parts_.size() > 0) printer->Print("\n");
+
+ for (int i = package_parts_.size() - 1; i >= 0; i--) {
+ printer->Print("} // namespace $part$\n",
+ "part", package_parts_[i]);
+ }
+}
+} // namespace ola
diff -urN ola-0.10.7/protoc/StrUtil.cpp ola-0.10.7-devel/protoc/StrUtil.cpp
--- ola-0.10.7/protoc/StrUtil.cpp 2016-12-12 01:00:42.000000000 +0200
+++ ola-0.10.7-devel/protoc/StrUtil.cpp 2019-11-22 13:25:13.343098041 +0200
@@ -253,8 +253,8 @@
}
char *FastHexToBuffer(int i, char* buffer) {
- GOOGLE_CHECK(i >= 0)
- << "FastHexToBuffer() wants non-negative integers, not " << i;
+ // GOOGLE_CHECK(i >= 0)
+ // << "FastHexToBuffer() wants non-negative integers, not " << i;
static const char *hexdigits = "0123456789abcdef";
char *p = buffer + 21;
@@ -433,7 +433,7 @@
u = u64 - (top_11_digits * 1000000000);
digits = u / 10000000; // 10,000,000
- GOOGLE_DCHECK_LT(digits, 100);
+ // GOOGLE_DCHECK_LT(digits, 100);
ASCII_digits = two_ASCII_digits[digits];
buffer[0] = ASCII_digits[0];
buffer[1] = ASCII_digits[1];
diff -urN ola-0.10.7/protoc/StrUtil.cpp.orig ola-0.10.7-devel/protoc/StrUtil.cpp.orig
--- ola-0.10.7/protoc/StrUtil.cpp.orig 1970-01-01 02:00:00.000000000 +0200
+++ ola-0.10.7-devel/protoc/StrUtil.cpp.orig 2016-12-12 01:00:42.000000000 +0200
@@ -0,0 +1,523 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// from google3/strings/strutil.cc
+
+#include <errno.h>
+#include <float.h> // FLT_DIG and DBL_DIG
+#include <limits.h>
+#include <stdio.h>
+#include <iterator>
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "protoc/StrUtil.h"
+
+#ifdef _WIN32
+// MSVC has only _snprintf, not snprintf.
+//
+// MinGW has both snprintf and _snprintf, but they appear to be different
+// functions. The former is buggy. When invoked like so:
+// char buffer[32];
+// snprintf(buffer, 32, "%.*g\n", FLT_DIG, 1.23e10f);
+// it prints "1.23000e+10". This is plainly wrong: %g should never print
+// trailing zeros after the decimal point. For some reason this bug only
+// occurs with some input values, not all. In any case, _snprintf does the
+// right thing, so we use it.
+#define snprintf _snprintf
+#endif // _WIN32
+
+namespace ola {
+
+// ----------------------------------------------------------------------
+// StringReplace()
+// Replace the "old" pattern with the "new" pattern in a string,
+// and append the result to "res". If replace_all is false,
+// it only replaces the first instance of "old."
+// ----------------------------------------------------------------------
+
+void StringReplace(const string& s, const string& oldsub,
+ const string& newsub, bool replace_all,
+ string* res) {
+ if (oldsub.empty()) {
+ res->append(s); // if empty, append the given string.
+ return;
+ }
+
+ string::size_type start_pos = 0;
+ string::size_type pos;
+ do {
+ pos = s.find(oldsub, start_pos);
+ if (pos == string::npos) {
+ break;
+ }
+ res->append(s, start_pos, pos - start_pos);
+ res->append(newsub);
+ start_pos = pos + oldsub.size(); // start searching again after the "old"
+ } while (replace_all);
+ res->append(s, start_pos, s.length() - start_pos);
+}
+
+// ----------------------------------------------------------------------
+// StringReplace()
+// Give me a string and two patterns "old" and "new", and I replace
+// the first instance of "old" in the string with "new", if it
+// exists. If "global" is true; call this repeatedly until it
+// fails. RETURN a new string, regardless of whether the replacement
+// happened or not.
+// ----------------------------------------------------------------------
+
+string StringReplace(const string& s, const string& oldsub,
+ const string& newsub, bool replace_all) {
+ string ret;
+ StringReplace(s, oldsub, newsub, replace_all, &ret);
+ return ret;
+}
+
+// ----------------------------------------------------------------------
+// SplitStringUsing()
+// Split a string using a character delimiter. Append the components
+// to 'result'.
+//
+// Note: For multi-character delimiters, this routine will split on *ANY* of
+// the characters in the string, not the entire string as a single delimiter.
+// ----------------------------------------------------------------------
+template <typename ITR>
+static inline
+void SplitStringToIteratorUsing(const string& full,
+ const char* delim,
+ ITR* result) {
+ // Optimize the common case where delim is a single character.
+ if (delim[0] != '\0' && delim[1] == '\0') {
+ char c = delim[0];
+ const char* p = full.data();
+ const char* end = p + full.size();
+ while (p != end) {
+ if (*p == c) {
+ ++p;
+ } else {
+ const char* start = p;
+ while (++p != end && *p != c) {
+ }
+ *(*result)++ = string(start, p - start);
+ }
+ }
+ return;
+ }
+
+ string::size_type begin_index, end_index;
+ begin_index = full.find_first_not_of(delim);
+ while (begin_index != string::npos) {
+ end_index = full.find_first_of(delim, begin_index);
+ if (end_index == string::npos) {
+ *(*result)++ = full.substr(begin_index);
+ return;
+ }
+ *(*result)++ = full.substr(begin_index, (end_index - begin_index));
+ begin_index = full.find_first_not_of(delim, end_index);
+ }
+}
+
+void SplitStringUsing(const string& full,
+ const char* delim,
+ vector<string>* result) {
+ std::back_insert_iterator< vector<string> > it(*result);
+ SplitStringToIteratorUsing(full, delim, &it);
+}
+
+// Protocol buffers doesn't ever care about errors, but I don't want to remove
+// the code.
+#define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false)
+
+// ----------------------------------------------------------------------
+// FastIntToBuffer()
+// FastInt64ToBuffer()
+// FastHexToBuffer()
+// FastHex64ToBuffer()
+// FastHex32ToBuffer()
+// ----------------------------------------------------------------------
+
+// Offset into buffer where FastInt64ToBuffer places the end of string
+// null character. Also used by FastInt64ToBufferLeft.
+static const int kFastInt64ToBufferOffset = 21;
+
+char *FastInt64ToBuffer(int64_t i, char* buffer) {
+ // We could collapse the positive and negative sections, but that
+ // would be slightly slower for positive numbers...
+ // 22 bytes is enough to store -2**64, -18446744073709551616.
+ char* p = buffer + kFastInt64ToBufferOffset;
+ *p-- = '\0';
+ if (i >= 0) {
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ return p + 1;
+ } else {
+ // On different platforms, % and / have different behaviors for
+ // negative numbers, so we need to jump through hoops to make sure
+ // we don't divide negative numbers.
+ if (i > -10) {
+ i = -i;
+ *p-- = '0' + i;
+ *p = '-';
+ return p;
+ } else {
+ // Make sure we aren't at MIN_INT, in which case we can't say i = -i
+ i = i + 10;
+ i = -i;
+ *p-- = '0' + i % 10;
+ // Undo what we did a moment ago
+ i = i / 10 + 1;
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ *p = '-';
+ return p;
+ }
+ }
+}
+
+// Offset into buffer where FastInt32ToBuffer places the end of string
+// null character. Also used by FastInt32ToBufferLeft
+static const int kFastInt32ToBufferOffset = 11;
+
+// Yes, this is a duplicate of FastInt64ToBuffer. But, we need this for the
+// compiler to generate 32 bit arithmetic instructions. It's much faster, at
+// least with 32 bit binaries.
+char *FastInt32ToBuffer(int32_t i, char* buffer) {
+ // We could collapse the positive and negative sections, but that
+ // would be slightly slower for positive numbers...
+ // 12 bytes is enough to store -2**32, -4294967296.
+ char* p = buffer + kFastInt32ToBufferOffset;
+ *p-- = '\0';
+ if (i >= 0) {
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ return p + 1;
+ } else {
+ // On different platforms, % and / have different behaviors for
+ // negative numbers, so we need to jump through hoops to make sure
+ // we don't divide negative numbers.
+ if (i > -10) {
+ i = -i;
+ *p-- = '0' + i;
+ *p = '-';
+ return p;
+ } else {
+ // Make sure we aren't at MIN_INT, in which case we can't say i = -i
+ i = i + 10;
+ i = -i;
+ *p-- = '0' + i % 10;
+ // Undo what we did a moment ago
+ i = i / 10 + 1;
+ do {
+ *p-- = '0' + i % 10;
+ i /= 10;
+ } while (i > 0);
+ *p = '-';
+ return p;
+ }
+ }
+}
+
+char *FastHexToBuffer(int i, char* buffer) {
+ GOOGLE_CHECK(i >= 0)
+ << "FastHexToBuffer() wants non-negative integers, not " << i;
+
+ static const char *hexdigits = "0123456789abcdef";
+ char *p = buffer + 21;
+ *p-- = '\0';
+ do {
+ *p-- = hexdigits[i & 15]; // mod by 16
+ i >>= 4; // divide by 16
+ } while (i > 0);
+ return p + 1;
+}
+
+char *InternalFastHexToBuffer(uint64_t value, char* buffer, int num_byte) {
+ static const char *hexdigits = "0123456789abcdef";
+ buffer[num_byte] = '\0';
+ for (int i = num_byte - 1; i >= 0; i--) {
+#ifdef _M_X64
+ // MSVC x64 platform has a bug optimizing the uint32_t(value) in the #else
+ // block. Given that the uint32_t cast was to improve performance on 32-bit
+ // platforms, we use 64-bit '&' directly.
+ buffer[i] = hexdigits[value & 0xf];
+#else
+ buffer[i] = hexdigits[uint32_t(value) & 0xf];
+#endif // _M_X64
+ value >>= 4;
+ }
+ return buffer;
+}
+
+char *FastHex64ToBuffer(uint64_t value, char* buffer) {
+ return InternalFastHexToBuffer(value, buffer, 16);
+}
+
+char *FastHex32ToBuffer(uint32_t value, char* buffer) {
+ return InternalFastHexToBuffer(value, buffer, 8);
+}
+
+// ----------------------------------------------------------------------
+// FastInt32ToBufferLeft()
+// FastUInt32ToBufferLeft()
+// FastInt64ToBufferLeft()
+// FastUInt64ToBufferLeft()
+//
+// Like the Fast*ToBuffer() functions above, these are intended for speed.
+// Unlike the Fast*ToBuffer() functions, however, these functions write
+// their output to the beginning of the buffer (hence the name, as the
+// output is left-aligned). The caller is responsible for ensuring that
+// the buffer has enough space to hold the output.
+//
+// Returns a pointer to the end of the string (i.e. the null character
+// terminating the string).
+// ----------------------------------------------------------------------
+
+static const char two_ASCII_digits[100][2] = {
+ {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'},
+ {'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},
+ {'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'},
+ {'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},
+ {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'},
+ {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
+ {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'},
+ {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},
+ {'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'},
+ {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},
+ {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'},
+ {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
+ {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'},
+ {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},
+ {'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'},
+ {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},
+ {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'},
+ {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
+ {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'},
+ {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}
+};
+
+char* FastUInt32ToBufferLeft(uint32_t u, char* buffer) {
+ int digits;
+ const char *ASCII_digits = NULL;
+ // The idea of this implementation is to trim the number of divides to as few
+ // as possible by using multiplication and subtraction rather than mod (%),
+ // and by outputting two digits at a time rather than one.
+ // The huge-number case is first, in the hopes that the compiler will output
+ // that case in one branch-free block of code, and only output conditional
+ // branches into it from below.
+ if (u >= 1000000000) { // >= 1,000,000,000
+ digits = u / 100000000; // 100,000,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ sublt100_000_000:
+ u -= digits * 100000000; // 100,000,000
+ lt100_000_000:
+ digits = u / 1000000; // 1,000,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ sublt1_000_000:
+ u -= digits * 1000000; // 1,000,000
+ lt1_000_000:
+ digits = u / 10000; // 10,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ sublt10_000:
+ u -= digits * 10000; // 10,000
+ lt10_000:
+ digits = u / 100;
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ sublt100:
+ u -= digits * 100;
+ lt100:
+ digits = u;
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ done:
+ *buffer = 0;
+ return buffer;
+ }
+
+ if (u < 100) {
+ digits = u;
+ if (u >= 10) goto lt100;
+ *buffer++ = '0' + digits;
+ goto done;
+ }
+ if (u < 10000) { // 10,000
+ if (u >= 1000) goto lt10_000;
+ digits = u / 100;
+ *buffer++ = '0' + digits;
+ goto sublt100;
+ }
+ if (u < 1000000) { // 1,000,000
+ if (u >= 100000) goto lt1_000_000;
+ digits = u / 10000; // 10,000
+ *buffer++ = '0' + digits;
+ goto sublt10_000;
+ }
+ if (u < 100000000) { // 100,000,000
+ if (u >= 10000000) goto lt100_000_000;
+ digits = u / 1000000; // 1,000,000
+ *buffer++ = '0' + digits;
+ goto sublt1_000_000;
+ }
+ // we already know that u < 1,000,000,000
+ digits = u / 100000000; // 100,000,000
+ *buffer++ = '0' + digits;
+ goto sublt100_000_000;
+}
+
+char* FastInt32ToBufferLeft(int32_t i, char* buffer) {
+ uint32_t u = i;
+ if (i < 0) {
+ *buffer++ = '-';
+ u = -i;
+ }
+ return FastUInt32ToBufferLeft(u, buffer);
+}
+
+char* FastUInt64ToBufferLeft(uint64_t u64, char* buffer) {
+ int digits;
+ const char *ASCII_digits = NULL;
+
+ uint32_t u = static_cast<uint32_t>(u64);
+ if (u == u64) return FastUInt32ToBufferLeft(u, buffer);
+
+ uint64_t top_11_digits = u64 / 1000000000;
+ buffer = FastUInt64ToBufferLeft(top_11_digits, buffer);
+ u = u64 - (top_11_digits * 1000000000);
+
+ digits = u / 10000000; // 10,000,000
+ GOOGLE_DCHECK_LT(digits, 100);
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ u -= digits * 10000000; // 10,000,000
+ digits = u / 100000; // 100,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ u -= digits * 100000; // 100,000
+ digits = u / 1000; // 1,000
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ u -= digits * 1000; // 1,000
+ digits = u / 10;
+ ASCII_digits = two_ASCII_digits[digits];
+ buffer[0] = ASCII_digits[0];
+ buffer[1] = ASCII_digits[1];
+ buffer += 2;
+ u -= digits * 10;
+ digits = u;
+ *buffer++ = '0' + digits;
+ *buffer = 0;
+ return buffer;
+}
+
+char* FastInt64ToBufferLeft(int64_t i, char* buffer) {
+ uint64_t u = i;
+ if (i < 0) {
+ *buffer++ = '-';
+ u = -i;
+ }
+ return FastUInt64ToBufferLeft(u, buffer);
+}
+
+// ----------------------------------------------------------------------
+// SimpleItoa()
+// Description: converts an integer to a string.
+//
+// Return value: string
+// ----------------------------------------------------------------------
+
+string SimpleItoa(int i) {
+ char buffer[kFastToBufferSize];
+ return (sizeof(i) == 4) ?
+ FastInt32ToBuffer(i, buffer) :
+ FastInt64ToBuffer(i, buffer);
+}
+
+string SimpleItoa(unsigned int i) {
+ char buffer[kFastToBufferSize];
+ return string(buffer, (sizeof(i) == 4) ?
+ FastUInt32ToBufferLeft(i, buffer) :
+ FastUInt64ToBufferLeft(i, buffer));
+}
+
+string SimpleItoa(long i) { // NOLINT(runtime/int)
+ char buffer[kFastToBufferSize];
+ return (sizeof(i) == 4) ?
+ FastInt32ToBuffer(i, buffer) :
+ FastInt64ToBuffer(i, buffer);
+}
+
+string SimpleItoa(unsigned long i) { // NOLINT(runtime/int)
+ char buffer[kFastToBufferSize];
+ return string(buffer, (sizeof(i) == 4) ?
+ FastUInt32ToBufferLeft(i, buffer) :
+ FastUInt64ToBufferLeft(i, buffer));
+}
+
+string SimpleItoa(long long i) { // NOLINT(runtime/int)
+ char buffer[kFastToBufferSize];
+ return (sizeof(i) == 4) ?
+ FastInt32ToBuffer(i, buffer) :
+ FastInt64ToBuffer(i, buffer);
+}
+
+string SimpleItoa(unsigned long long i) { // NOLINT(runtime/int)
+ char buffer[kFastToBufferSize];
+ return string(buffer, (sizeof(i) == 4) ?
+ FastUInt32ToBufferLeft(i, buffer) :
+ FastUInt64ToBufferLeft(i, buffer));
+}
+} // namespace ola