15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/ 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met: 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions of source code must retain the above copyright 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions in binary form must reproduce the above 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Neither the name of Google Inc. nor the names of its 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from google3/strings/strutil.cc 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/strutil.h> 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <float.h> // FLT_DIG and DBL_DIG 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits.h> 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iterator> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _WIN32 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MSVC has only _snprintf, not snprintf. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MinGW has both snprintf and _snprintf, but they appear to be different 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions. The former is buggy. When invoked like so: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// char buffer[32]; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// snprintf(buffer, 32, "%.*g\n", FLT_DIG, 1.23e10f); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it prints "1.23000e+10". This is plainly wrong: %g should never print 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// trailing zeros after the decimal point. For some reason this bug only 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// occurs with some input values, not all. In any case, _snprintf does the 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// right thing, so we use it. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define snprintf _snprintf 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool IsNaN(double value) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NaN is never equal to anything, even itself. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value != value; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These are defined as macros on some platforms. #undef them so that we can 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// redefine them. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef isxdigit 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef isprint 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The definitions of these in ctype.h change based on locale. Since our 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// string manipulation is all in relation to the protocol buffer and C++ 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// languages, we always want to use the C locale. So, we re-define these 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// exactly as we want them. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool isxdigit(char c) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ('0' <= c && c <= '9') || 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('a' <= c && c <= 'f') || 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ('A' <= c && c <= 'F'); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool isprint(char c) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return c >= 0x20 && c <= 0x7E; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StripString 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Replaces any occurrence of the character 'remove' (or the characters 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in 'remove') with the character 'replacewith'. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StripString(string* s, const char* remove, char replacewith) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char * str_start = s->c_str(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char * str = str_start; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (str = strpbrk(str, remove); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str != NULL; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = strpbrk(str + 1, remove)) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*s)[str - str_start] = replacewith; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StringReplace() 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Replace the "old" pattern with the "new" pattern in a string, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and append the result to "res". If replace_all is false, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it only replaces the first instance of "old." 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StringReplace(const string& s, const string& oldsub, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& newsub, bool replace_all, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string* res) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (oldsub.empty()) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res->append(s); // if empty, append the given string. 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string::size_type start_pos = 0; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string::size_type pos; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos = s.find(oldsub, start_pos); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pos == string::npos) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res->append(s, start_pos, pos - start_pos); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res->append(newsub); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_pos = pos + oldsub.size(); // start searching again after the "old" 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (replace_all); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res->append(s, start_pos, s.length() - start_pos); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StringReplace() 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Give me a string and two patterns "old" and "new", and I replace 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the first instance of "old" in the string with "new", if it 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// exists. If "global" is true; call this repeatedly until it 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fails. RETURN a new string, regardless of whether the replacement 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// happened or not. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string StringReplace(const string& s, const string& oldsub, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& newsub, bool replace_all) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string ret; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringReplace(s, oldsub, newsub, replace_all, &ret); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SplitStringUsing() 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Split a string using a character delimiter. Append the components 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to 'result'. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: For multi-character delimiters, this routine will split on *ANY* of 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the characters in the string, not the entire string as a single delimiter. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename ITR> 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SplitStringToIteratorUsing(const string& full, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* delim, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ITR& result) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Optimize the common case where delim is a single character. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delim[0] != '\0' && delim[1] == '\0') { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char c = delim[0]; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* p = full.data(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* end = p + full.size(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (p != end) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*p == c) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++p; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* start = p; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (++p != end && *p != c); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result++ = string(start, p - start); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string::size_type begin_index, end_index; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) begin_index = full.find_first_not_of(delim); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (begin_index != string::npos) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_index = full.find_first_of(delim, begin_index); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (end_index == string::npos) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result++ = full.substr(begin_index); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result++ = full.substr(begin_index, (end_index - begin_index)); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) begin_index = full.find_first_not_of(delim, end_index); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SplitStringUsing(const string& full, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* delim, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<string>* result) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) back_insert_iterator< vector<string> > it(*result); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SplitStringToIteratorUsing(full, delim, it); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Split a string using a character delimiter. Append the components 193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// to 'result'. If there are consecutive delimiters, this function 194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// will return corresponding empty strings. The string is split into 195ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// at most the specified number of pieces greedily. This means that the 196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// last piece may possibly be split further. To split into as many pieces 197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// as possible, specify 0 as the number of pieces. 198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// If "full" is the empty string, yields an empty string as the only value. 200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// 201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// If "pieces" is negative for some reason, it returns the whole string 202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// ---------------------------------------------------------------------- 203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochtemplate <typename StringType, typename ITR> 204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic inline 205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid SplitStringToIteratorAllowEmpty(const StringType& full, 206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const char* delim, 207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int pieces, 208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ITR& result) { 209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch string::size_type begin_index, end_index; 210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch begin_index = 0; 211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (int i = 0; (i < pieces-1) || (pieces == 0); i++) { 213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch end_index = full.find_first_of(delim, begin_index); 214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (end_index == string::npos) { 215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch *result++ = full.substr(begin_index); 216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 217ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch *result++ = full.substr(begin_index, (end_index - begin_index)); 219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch begin_index = end_index + 1; 220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch *result++ = full.substr(begin_index); 222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 223ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid SplitStringAllowEmpty(const string& full, const char* delim, 225ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch vector<string>* result) { 226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch back_insert_iterator<vector<string> > it(*result); 227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SplitStringToIteratorAllowEmpty(full, delim, 0, it); 228ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// JoinStrings() 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This merges a vector of string components with delim inserted 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as separaters between components. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class ITERATOR> 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void JoinStringsIterator(const ITERATOR& start, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ITERATOR& end, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* delim, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string* result) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_CHECK(result != NULL); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delim_length = strlen(delim); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Precompute resulting length so we can reserve() memory in one shot. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int length = 0; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ITERATOR iter = start; iter != end; ++iter) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != start) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length += delim_length; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length += iter->size(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->reserve(length); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now combine everything. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ITERATOR iter = start; iter != end; ++iter) { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != start) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->append(delim, delim_length); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->append(iter->data(), iter->size()); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JoinStrings(const vector<string>& components, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* delim, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string * result) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JoinStringsIterator(components.begin(), components.end(), delim, result); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// UnescapeCEscapeSequences() 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This does all the unescaping that C does: \ooo, \r, \n, etc 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns length of resulting string. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The implementation of \x parses any positive number of hex digits, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but it is an error if the value requires more than 8 bits, and the 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// result is truncated to 8 bits. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The second call stores its errors in a supplied string vector. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the string vector pointer is NULL, it reports the errors with LOG(). 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7')) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int hex_digit_to_int(char c) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Assume ASCII. */ 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(isxdigit(c)); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = static_cast<unsigned char>(c); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (x > '9') { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x += 9; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return x & 0xf; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol buffers doesn't ever care about errors, but I don't want to remove 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the code. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UnescapeCEscapeSequences(const char* source, char* dest) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UnescapeCEscapeSequences(source, dest, NULL); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UnescapeCEscapeSequences(const char* source, char* dest, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<string> *errors) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_DCHECK(errors == NULL) << "Error reporting not implemented."; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* d = dest; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* p = source; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Small optimization for case where source = dest and there's no escaping 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ( p == d && *p != '\0' && *p != '\\' ) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p++, d++; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*p != '\0') { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*p != '\\') { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *d++ = *p++; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch ( *++p ) { // skip past the '\\' 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\0': 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_STRING(ERROR, errors) << "String cannot end with \\"; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *d = '\0'; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return d - dest; // we're done with p 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'a': *d++ = '\a'; break; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'b': *d++ = '\b'; break; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'f': *d++ = '\f'; break; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'n': *d++ = '\n'; break; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'r': *d++ = '\r'; break; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 't': *d++ = '\t'; break; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'v': *d++ = '\v'; break; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\\': *d++ = '\\'; break; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '?': *d++ = '\?'; break; // \? Who knew? 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\'': *d++ = '\''; break; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '"': *d++ = '\"'; break; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '0': case '1': case '2': case '3': // octal digit: 1 to 3 digits 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '4': case '5': case '6': case '7': { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char ch = *p - '0'; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( IS_OCTAL_DIGIT(p[1]) ) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ch = ch * 8 + *++p - '0'; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( IS_OCTAL_DIGIT(p[1]) ) // safe (and easy) to do this twice 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ch = ch * 8 + *++p - '0'; // now points at last digit 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *d++ = ch; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'x': case 'X': { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!isxdigit(p[1])) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p[1] == '\0') { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_STRING(ERROR, errors) << "String cannot end with \\x"; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_STRING(ERROR, errors) << 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\\x cannot be followed by non-hex digit: \\" << *p << p[1]; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int ch = 0; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *hex_start = p; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (isxdigit(p[1])) // arbitrarily many hex digits 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ch = (ch << 4) + hex_digit_to_int(*++p); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ch > 0xFF) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_STRING(ERROR, errors) << "Value of " << 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\\" << string(hex_start, p+1-hex_start) << " exceeds 8 bits"; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *d++ = ch; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 // TODO(kenton): Support \u and \U? Requires runetochar(). 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'u': { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // \uhhhh => convert 4 hex digits to UTF-8 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char32 rune = 0; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *hex_start = p; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 4; ++i) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isxdigit(p[1])) { // Look one char ahead. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rune = (rune << 4) + hex_digit_to_int(*++p); // Advance p. 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_STRING(ERROR, errors) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\\u must be followed by 4 hex digits: \\" 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << string(hex_start, p+1-hex_start); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d += runetochar(d, &rune); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 'U': { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // \Uhhhhhhhh => convert 8 hex digits to UTF-8 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char32 rune = 0; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *hex_start = p; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 8; ++i) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isxdigit(p[1])) { // Look one char ahead. 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't change rune until we're sure this 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is within the Unicode limit, but do advance p. 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char32 newrune = (rune << 4) + hex_digit_to_int(*++p); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newrune > 0x10FFFF) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_STRING(ERROR, errors) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Value of \\" 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << string(hex_start, p + 1 - hex_start) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " exceeds Unicode limit (0x10FFFF)"; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rune = newrune; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_STRING(ERROR, errors) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\\U must be followed by 8 hex digits: \\" 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << string(hex_start, p+1-hex_start); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d += runetochar(d, &rune); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_STRING(ERROR, errors) << "Unknown escape sequence: \\" << *p; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p++; // read past letter we escaped 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *d = '\0'; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return d - dest; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// UnescapeCEscapeString() 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This does the same thing as UnescapeCEscapeSequences, but creates 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a new string. The caller does not need to worry about allocating 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a dest buffer. This should be used for non performance critical 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tasks such as printing debug messages. It is safe for src and dest 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be the same. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The second call stores its errors in a supplied string vector. 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the string vector pointer is NULL, it reports the errors with LOG(). 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the first and second calls, the length of dest is returned. In the 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the third call, the new string is returned. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UnescapeCEscapeString(const string& src, string* dest) { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UnescapeCEscapeString(src, dest, NULL); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UnescapeCEscapeString(const string& src, string* dest, 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<string> *errors) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_array<char> unescaped(new char[src.size() + 1]); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), errors); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_CHECK(dest); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest->assign(unescaped.get(), len); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return len; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string UnescapeCEscapeString(const string& src) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_array<char> unescaped(new char[src.size() + 1]); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), NULL); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return string(unescaped.get(), len); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CEscapeString() 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CHexEscapeString() 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copies 'src' to 'dest', escaping dangerous characters using 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// C-style escape sequences. This is very useful for preparing query 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// flags. 'src' and 'dest' should not overlap. The 'Hex' version uses 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hexadecimal rather than octal sequences. 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the number of bytes written to 'dest' (not including the \0) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or -1 if there was insufficient space. 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CEscapeInternal(const char* src, int src_len, char* dest, 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dest_len, bool use_hex, bool utf8_safe) { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* src_end = src + src_len; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int used = 0; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool last_hex_escape = false; // true if last output char was \xNN 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; src < src_end; src++) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dest_len - used < 2) // Need space for two letter escape 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_hex_escape = false; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (*src) { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\n': dest[used++] = '\\'; dest[used++] = 'n'; break; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\r': dest[used++] = '\\'; dest[used++] = 'r'; break; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\t': dest[used++] = '\\'; dest[used++] = 't'; break; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\'': dest[used++] = '\\'; dest[used++] = '\''; break; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that if we emit \xNN and the src character after that is a hex 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // digit then that digit must be escaped too to prevent it being 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // interpreted as part of the character code by C. 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((!utf8_safe || static_cast<uint8>(*src) < 0x80) && 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!isprint(*src) || 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (last_hex_escape && isxdigit(*src)))) { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dest_len - used < 4) // need space for 4 letter escape 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"), 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint8>(*src)); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_hex_escape = use_hex; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) used += 4; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest[used++] = *src; break; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_hex_escape = is_hex_escape; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dest_len - used < 1) // make sure that there is room for \0 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest[used] = '\0'; // doesn't count towards return value though 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return used; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CEscapeString(const char* src, int src_len, char* dest, int dest_len) { 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CEscapeInternal(src, src_len, dest, dest_len, false, false); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CEscape() 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CHexEscape() 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copies 'src' to result, escaping dangerous characters using 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// C-style escape sequences. This is very useful for preparing query 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// flags. 'src' and 'dest' should not overlap. The 'Hex' version 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hexadecimal rather than octal sequences. 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped. 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string CEscape(const string& src) { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int dest_length = src.size() * 4 + 1; // Maximum possible expansion 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_array<char> dest(new char[dest_length]); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int len = CEscapeInternal(src.data(), src.size(), 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.get(), dest_length, false, false); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_DCHECK_GE(len, 0); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return string(dest.get(), len); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace strings { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Utf8SafeCEscape(const string& src) { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int dest_length = src.size() * 4 + 1; // Maximum possible expansion 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_array<char> dest(new char[dest_length]); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int len = CEscapeInternal(src.data(), src.size(), 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.get(), dest_length, false, true); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_DCHECK_GE(len, 0); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return string(dest.get(), len); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string CHexEscape(const string& src) { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int dest_length = src.size() * 4 + 1; // Maximum possible expansion 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_array<char> dest(new char[dest_length]); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int len = CEscapeInternal(src.data(), src.size(), 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.get(), dest_length, true, false); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_DCHECK_GE(len, 0); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return string(dest.get(), len); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace strings 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// strto32_adaptor() 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// strtou32_adaptor() 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implementation of strto[u]l replacements that have identical 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// overflow and underflow characteristics for both ILP-32 and LP-64 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// platforms, including errno preservation in error-free calls. 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32 strto32_adaptor(const char *nptr, char **endptr, int base) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int saved_errno = errno; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = 0; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const long result = strtol(nptr, endptr, base); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno == ERANGE && result == LONG_MIN) { 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kint32min; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (errno == ERANGE && result == LONG_MAX) { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kint32max; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (errno == 0 && result < kint32min) { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = ERANGE; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kint32min; 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (errno == 0 && result > kint32max) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = ERANGE; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kint32max; 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno == 0) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = saved_errno; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int32>(result); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 strtou32_adaptor(const char *nptr, char **endptr, int base) { 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int saved_errno = errno; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = 0; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned long result = strtoul(nptr, endptr, base); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno == ERANGE && result == ULONG_MAX) { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kuint32max; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (errno == 0 && result > kuint32max) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = ERANGE; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kuint32max; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno == 0) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = saved_errno; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<uint32>(result); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastIntToBuffer() 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastInt64ToBuffer() 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastHexToBuffer() 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastHex64ToBuffer() 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastHex32ToBuffer() 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Offset into buffer where FastInt64ToBuffer places the end of string 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// null character. Also used by FastInt64ToBufferLeft. 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kFastInt64ToBufferOffset = 21; 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *FastInt64ToBuffer(int64 i, char* buffer) { 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We could collapse the positive and negative sections, but that 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // would be slightly slower for positive numbers... 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 22 bytes is enough to store -2**64, -18446744073709551616. 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* p = buffer + kFastInt64ToBufferOffset; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '\0'; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i >= 0) { 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + i % 10; 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i /= 10; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (i > 0); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p + 1; 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On different platforms, % and / have different behaviors for 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // negative numbers, so we need to jump through hoops to make sure 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we don't divide negative numbers. 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i > -10) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = -i; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + i; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = '-'; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we aren't at MIN_INT, in which case we can't say i = -i 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = i + 10; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = -i; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + i % 10; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Undo what we did a moment ago 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = i / 10 + 1; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + i % 10; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i /= 10; 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (i > 0); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = '-'; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Offset into buffer where FastInt32ToBuffer places the end of string 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// null character. Also used by FastInt32ToBufferLeft 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kFastInt32ToBufferOffset = 11; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Yes, this is a duplicate of FastInt64ToBuffer. But, we need this for the 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// compiler to generate 32 bit arithmetic instructions. It's much faster, at 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// least with 32 bit binaries. 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *FastInt32ToBuffer(int32 i, char* buffer) { 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We could collapse the positive and negative sections, but that 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // would be slightly slower for positive numbers... 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 12 bytes is enough to store -2**32, -4294967296. 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* p = buffer + kFastInt32ToBufferOffset; 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '\0'; 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i >= 0) { 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + i % 10; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i /= 10; 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (i > 0); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p + 1; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On different platforms, % and / have different behaviors for 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // negative numbers, so we need to jump through hoops to make sure 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we don't divide negative numbers. 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i > -10) { 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = -i; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + i; 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = '-'; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we aren't at MIN_INT, in which case we can't say i = -i 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = i + 10; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = -i; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + i % 10; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Undo what we did a moment ago 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = i / 10 + 1; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + i % 10; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i /= 10; 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (i > 0); 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = '-'; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *FastHexToBuffer(int i, char* buffer) { 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_CHECK(i >= 0) << "FastHexToBuffer() wants non-negative integers, not " << i; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char *hexdigits = "0123456789abcdef"; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p = buffer + 21; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '\0'; 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = hexdigits[i & 15]; // mod by 16 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i >>= 4; // divide by 16 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (i > 0); 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p + 1; 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *InternalFastHexToBuffer(uint64 value, char* buffer, int num_byte) { 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char *hexdigits = "0123456789abcdef"; 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[num_byte] = '\0'; 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = num_byte - 1; i >= 0; i--) { 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _M_X64 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MSVC x64 platform has a bug optimizing the uint32(value) in the #else 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // block. Given that the uint32 cast was to improve performance on 32-bit 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // platforms, we use 64-bit '&' directly. 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[i] = hexdigits[value & 0xf]; 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[i] = hexdigits[uint32(value) & 0xf]; 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value >>= 4; 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *FastHex64ToBuffer(uint64 value, char* buffer) { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InternalFastHexToBuffer(value, buffer, 16); 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *FastHex32ToBuffer(uint32 value, char* buffer) { 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InternalFastHexToBuffer(value, buffer, 8); 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline char* PlaceNum(char* p, int num, char prev_sep) { 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + num % 10; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = '0' + num / 10; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p-- = prev_sep; 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastInt32ToBufferLeft() 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastUInt32ToBufferLeft() 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastInt64ToBufferLeft() 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FastUInt64ToBufferLeft() 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Like the Fast*ToBuffer() functions above, these are intended for speed. 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Unlike the Fast*ToBuffer() functions, however, these functions write 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// their output to the beginning of the buffer (hence the name, as the 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// output is left-aligned). The caller is responsible for ensuring that 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the buffer has enough space to hold the output. 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a pointer to the end of the string (i.e. the null character 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// terminating the string). 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char two_ASCII_digits[100][2] = { 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'0','0'}, {'0','1'}, {'0','2'}, {'0','3'}, {'0','4'}, 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'0','5'}, {'0','6'}, {'0','7'}, {'0','8'}, {'0','9'}, 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'1','0'}, {'1','1'}, {'1','2'}, {'1','3'}, {'1','4'}, 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'1','5'}, {'1','6'}, {'1','7'}, {'1','8'}, {'1','9'}, 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'2','0'}, {'2','1'}, {'2','2'}, {'2','3'}, {'2','4'}, 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'2','5'}, {'2','6'}, {'2','7'}, {'2','8'}, {'2','9'}, 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'3','0'}, {'3','1'}, {'3','2'}, {'3','3'}, {'3','4'}, 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'3','5'}, {'3','6'}, {'3','7'}, {'3','8'}, {'3','9'}, 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'4','0'}, {'4','1'}, {'4','2'}, {'4','3'}, {'4','4'}, 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'4','5'}, {'4','6'}, {'4','7'}, {'4','8'}, {'4','9'}, 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'5','0'}, {'5','1'}, {'5','2'}, {'5','3'}, {'5','4'}, 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'5','5'}, {'5','6'}, {'5','7'}, {'5','8'}, {'5','9'}, 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'6','0'}, {'6','1'}, {'6','2'}, {'6','3'}, {'6','4'}, 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'6','5'}, {'6','6'}, {'6','7'}, {'6','8'}, {'6','9'}, 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'7','0'}, {'7','1'}, {'7','2'}, {'7','3'}, {'7','4'}, 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'7','5'}, {'7','6'}, {'7','7'}, {'7','8'}, {'7','9'}, 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'8','0'}, {'8','1'}, {'8','2'}, {'8','3'}, {'8','4'}, 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'8','5'}, {'8','6'}, {'8','7'}, {'8','8'}, {'8','9'}, 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'9','0'}, {'9','1'}, {'9','2'}, {'9','3'}, {'9','4'}, 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {'9','5'}, {'9','6'}, {'9','7'}, {'9','8'}, {'9','9'} 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* FastUInt32ToBufferLeft(uint32 u, char* buffer) { 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int digits; 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *ASCII_digits = NULL; 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The idea of this implementation is to trim the number of divides to as few 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as possible by using multiplication and subtraction rather than mod (%), 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and by outputting two digits at a time rather than one. 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The huge-number case is first, in the hopes that the compiler will output 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that case in one branch-free block of code, and only output conditional 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // branches into it from below. 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u >= 1000000000) { // >= 1,000,000,000 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 100000000; // 100,000,000 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCII_digits = two_ASCII_digits[digits]; 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = ASCII_digits[0]; 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[1] = ASCII_digits[1]; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer += 2; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sublt100_000_000: 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u -= digits * 100000000; // 100,000,000 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)lt100_000_000: 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 1000000; // 1,000,000 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCII_digits = two_ASCII_digits[digits]; 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = ASCII_digits[0]; 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[1] = ASCII_digits[1]; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer += 2; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sublt1_000_000: 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u -= digits * 1000000; // 1,000,000 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)lt1_000_000: 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 10000; // 10,000 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCII_digits = two_ASCII_digits[digits]; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = ASCII_digits[0]; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[1] = ASCII_digits[1]; 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer += 2; 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sublt10_000: 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u -= digits * 10000; // 10,000 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)lt10_000: 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 100; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCII_digits = two_ASCII_digits[digits]; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = ASCII_digits[0]; 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[1] = ASCII_digits[1]; 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer += 2; 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sublt100: 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u -= digits * 100; 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)lt100: 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u; 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCII_digits = two_ASCII_digits[digits]; 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = ASCII_digits[0]; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[1] = ASCII_digits[1]; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer += 2; 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)done: 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer = 0; 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u < 100) { 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u; 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u >= 10) goto lt100; 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer++ = '0' + digits; 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto done; 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u < 10000) { // 10,000 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u >= 1000) goto lt10_000; 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 100; 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer++ = '0' + digits; 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto sublt100; 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u < 1000000) { // 1,000,000 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u >= 100000) goto lt1_000_000; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 10000; // 10,000 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer++ = '0' + digits; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto sublt10_000; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u < 100000000) { // 100,000,000 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u >= 10000000) goto lt100_000_000; 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 1000000; // 1,000,000 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer++ = '0' + digits; 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto sublt1_000_000; 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we already know that u < 1,000,000,000 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 100000000; // 100,000,000 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer++ = '0' + digits; 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto sublt100_000_000; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* FastInt32ToBufferLeft(int32 i, char* buffer) { 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 u = i; 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < 0) { 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer++ = '-'; 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u = -i; 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FastUInt32ToBufferLeft(u, buffer); 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* FastUInt64ToBufferLeft(uint64 u64, char* buffer) { 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int digits; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *ASCII_digits = NULL; 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 u = static_cast<uint32>(u64); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (u == u64) return FastUInt32ToBufferLeft(u, buffer); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 top_11_digits = u64 / 1000000000; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer = FastUInt64ToBufferLeft(top_11_digits, buffer); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u = u64 - (top_11_digits * 1000000000); 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 10000000; // 10,000,000 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_DCHECK_LT(digits, 100); 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCII_digits = two_ASCII_digits[digits]; 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = ASCII_digits[0]; 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[1] = ASCII_digits[1]; 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer += 2; 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u -= digits * 10000000; // 10,000,000 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 100000; // 100,000 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCII_digits = two_ASCII_digits[digits]; 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = ASCII_digits[0]; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[1] = ASCII_digits[1]; 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer += 2; 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u -= digits * 100000; // 100,000 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 1000; // 1,000 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCII_digits = two_ASCII_digits[digits]; 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = ASCII_digits[0]; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[1] = ASCII_digits[1]; 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer += 2; 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u -= digits * 1000; // 1,000 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u / 10; 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASCII_digits = two_ASCII_digits[digits]; 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[0] = ASCII_digits[0]; 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer[1] = ASCII_digits[1]; 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer += 2; 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u -= digits * 10; 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) digits = u; 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer++ = '0' + digits; 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer = 0; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* FastInt64ToBufferLeft(int64 i, char* buffer) { 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 u = i; 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < 0) { 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer++ = '-'; 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u = -i; 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FastUInt64ToBufferLeft(u, buffer); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SimpleItoa() 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Description: converts an integer to a string. 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return value: string 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string SimpleItoa(int i) { 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kFastToBufferSize]; 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (sizeof(i) == 4) ? 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastInt32ToBuffer(i, buffer) : 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastInt64ToBuffer(i, buffer); 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string SimpleItoa(unsigned int i) { 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kFastToBufferSize]; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return string(buffer, (sizeof(i) == 4) ? 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastUInt32ToBufferLeft(i, buffer) : 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastUInt64ToBufferLeft(i, buffer)); 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string SimpleItoa(long i) { 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kFastToBufferSize]; 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (sizeof(i) == 4) ? 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastInt32ToBuffer(i, buffer) : 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastInt64ToBuffer(i, buffer); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string SimpleItoa(unsigned long i) { 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kFastToBufferSize]; 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return string(buffer, (sizeof(i) == 4) ? 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastUInt32ToBufferLeft(i, buffer) : 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastUInt64ToBufferLeft(i, buffer)); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string SimpleItoa(long long i) { 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kFastToBufferSize]; 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (sizeof(i) == 4) ? 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastInt32ToBuffer(i, buffer) : 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastInt64ToBuffer(i, buffer); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string SimpleItoa(unsigned long long i) { 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kFastToBufferSize]; 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return string(buffer, (sizeof(i) == 4) ? 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastUInt32ToBufferLeft(i, buffer) : 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FastUInt64ToBufferLeft(i, buffer)); 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SimpleDtoa() 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SimpleFtoa() 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DoubleToBuffer() 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FloatToBuffer() 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We want to print the value without losing precision, but we also do 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not want to print more digits than necessary. This turns out to be 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// trickier than it sounds. Numbers like 0.2 cannot be represented 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// exactly in binary. If we print 0.2 with a very large precision, 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// e.g. "%.50g", we get "0.2000000000000000111022302462515654042363167". 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On the other hand, if we set the precision too low, we lose 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// significant digits when printing numbers that actually need them. 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It turns out there is no precision value that does the right thing 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for all numbers. 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Our strategy is to first try printing with a precision that is never 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// over-precise, then parse the result with strtod() to see if it 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// matches. If not, we print again with a precision that will always 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// give a precise result, but may use more digits than necessary. 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An arguably better strategy would be to use the algorithm described 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in "How to Print Floating-Point Numbers Accurately" by Steele & 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// White, e.g. as implemented by David M. Gay's dtoa(). It turns out, 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// however, that the following implementation is about as fast as 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DMG's code. Furthermore, DMG's code locks mutexes, which means it 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will not scale well on multi-core machines. DMG's code is slightly 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// more accurate (in that it will never use more digits than 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// necessary), but this is probably irrelevant for most users. 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Rob Pike and Ken Thompson also have an implementation of dtoa() in 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// third_party/fmt/fltfmt.cc. Their implementation is similar to this 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// one in that it makes guesses and then uses strtod() to check them. 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Their implementation is faster because they use their own code to 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// generate the digits in the first place rather than use snprintf(), 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thus avoiding format string parsing overhead. However, this makes 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it considerably more complicated than the following implementation, 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and it is embedded in a larger library. If speed turns out to be 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an issue, we could re-implement this in terms of their 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implementation. 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string SimpleDtoa(double value) { 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kDoubleToBufferSize]; 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoubleToBuffer(value, buffer); 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string SimpleFtoa(float value) { 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kFloatToBufferSize]; 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FloatToBuffer(value, buffer); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool IsValidFloatChar(char c) { 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ('0' <= c && c <= '9') || 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c == 'e' || c == 'E' || 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c == '+' || c == '-'; 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DelocalizeRadix(char* buffer) { 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fast check: if the buffer has a normal decimal point, assume no 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // translation is needed. 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strchr(buffer, '.') != NULL) return; 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the first unknown character. 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (IsValidFloatChar(*buffer)) ++buffer; 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*buffer == '\0') { 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No radix character found. 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are now pointing at the locale-specific radix character. Replace it 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with '.'. 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer = '.'; 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++buffer; 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsValidFloatChar(*buffer) && *buffer != '\0') { 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It appears the radix was a multi-byte character. We need to remove the 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extra bytes. 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* target = buffer; 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { ++buffer; } while (!IsValidFloatChar(*buffer) && *buffer != '\0'); 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memmove(target, buffer, strlen(buffer) + 1); 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* DoubleToBuffer(double value, char* buffer) { 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // platforms these days. Just in case some system exists where DBL_DIG 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is significantly larger -- and risks overflowing our buffer -- we have 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this assert. 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_COMPILE_ASSERT(DBL_DIG < 20, DBL_DIG_is_too_big); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value == numeric_limits<double>::infinity()) { 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy(buffer, "inf"); 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (value == -numeric_limits<double>::infinity()) { 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy(buffer, "-inf"); 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (IsNaN(value)) { 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy(buffer, "nan"); 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int snprintf_result = 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG, value); 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The snprintf should never overflow because the buffer is significantly 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // larger than the precision we asked for. 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize); 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to make parsed_value volatile in order to force the compiler to 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // write it out to the stack. Otherwise, it may keep the value in a 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // register, and if it does that, it may keep it as a long double instead 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of a double. This long double may have extra bits that make it compare 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unequal to "value" even though it would be exactly equal if it were 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // truncated to a double. 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) volatile double parsed_value = strtod(buffer, NULL); 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parsed_value != value) { 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int snprintf_result = 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG+2, value); 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should never overflow; see above. 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DelocalizeRadix(buffer); 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool safe_strtof(const char* str, float* value) { 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* endptr; 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = 0; // errno only gets set on errors 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_WIN32) || defined (__hpux) // has no strtof() 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *value = strtod(str, &endptr); 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *value = strtof(str, &endptr); 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *str != 0 && *endptr == 0 && errno == 0; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* FloatToBuffer(float value, char* buffer) { 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // platforms these days. Just in case some system exists where FLT_DIG 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is significantly larger -- and risks overflowing our buffer -- we have 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this assert. 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_COMPILE_ASSERT(FLT_DIG < 10, FLT_DIG_is_too_big); 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value == numeric_limits<double>::infinity()) { 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy(buffer, "inf"); 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (value == -numeric_limits<double>::infinity()) { 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy(buffer, "-inf"); 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (IsNaN(value)) { 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy(buffer, "nan"); 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int snprintf_result = 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG, value); 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The snprintf should never overflow because the buffer is significantly 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // larger than the precision we asked for. 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize); 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float parsed_value; 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) { 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int snprintf_result = 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG+2, value); 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should never overflow; see above. 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize); 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DelocalizeRadix(buffer); 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NoLocaleStrtod() 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code will make you cry. 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------- 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a string identical to *input except that the character pointed to 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by radix_pos (which should be '.') is replaced with the locale-specific 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// radix character. 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string LocalizeRadix(const char* input, const char* radix_pos) { 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine the locale-specific radix character by calling sprintf() to 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // print the number 1.5, then stripping off the digits. As far as I can 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tell, this is the only portable, thread-safe way to get the C library 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to divuldge the locale's radix character. No, localeconv() is NOT 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread-safe. 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char temp[16]; 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size = sprintf(temp, "%.1f", 1.5); 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_CHECK_EQ(temp[0], '1'); 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_CHECK_EQ(temp[size-1], '5'); 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GOOGLE_CHECK_LE(size, 6); 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now replace the '.' in the input with it. 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string result; 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.reserve(strlen(input) + size - 3); 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.append(input, radix_pos); 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.append(temp + 1, size - 2); 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.append(radix_pos + 1); 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double NoLocaleStrtod(const char* text, char** original_endptr) { 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We cannot simply set the locale to "C" temporarily with setlocale() 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as this is not thread-safe. Instead, we try to parse in the current 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // locale first. If parsing stops at a '.' character, then this is a 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pretty good hint that we're actually in some other locale in which 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // '.' is not the radix character. 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* temp_endptr; 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double result = strtod(text, &temp_endptr); 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original_endptr != NULL) *original_endptr = temp_endptr; 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*temp_endptr != '.') return result; 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parsing halted on a '.'. Perhaps we're in a different locale? Let's 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // try to replace the '.' with a locale-specific radix character and 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // try again. 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string localized = LocalizeRadix(text, temp_endptr); 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* localized_cstr = localized.c_str(); 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* localized_endptr; 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = strtod(localized_cstr, &localized_endptr); 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((localized_endptr - localized_cstr) > 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (temp_endptr - text)) { 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This attempt got further, so replacing the decimal must have helped. 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update original_endptr to point at the right location. 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original_endptr != NULL) { 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size_diff is non-zero if the localized radix has multiple bytes. 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int size_diff = localized.size() - strlen(text); 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // const_cast is necessary to match the strtod() interface. 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *original_endptr = const_cast<char*>( 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text + (localized_endptr - localized_cstr - size_diff)); 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace protobuf 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace google 1212