util.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*
  2. * Copyright 2014 Google Inc. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef FLATBUFFERS_UTIL_H_
  17. #define FLATBUFFERS_UTIL_H_
  18. #include <fstream>
  19. #include <iomanip>
  20. #include <string>
  21. #include <sstream>
  22. #include <stdint.h>
  23. #include <stdlib.h>
  24. #include <assert.h>
  25. #ifdef _WIN32
  26. #ifndef WIN32_LEAN_AND_MEAN
  27. #define WIN32_LEAN_AND_MEAN
  28. #endif
  29. #ifndef NOMINMAX
  30. #define NOMINMAX
  31. #endif
  32. #include <windows.h>
  33. #include <winbase.h>
  34. #include <direct.h>
  35. #else
  36. #include <limits.h>
  37. #endif
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include "flatbuffers/flatbuffers.h"
  41. namespace flatbuffers {
  42. // Convert an integer or floating point value to a string.
  43. // In contrast to std::stringstream, "char" values are
  44. // converted to a string of digits, and we don't use scientific notation.
  45. template<typename T> std::string NumToString(T t) {
  46. std::stringstream ss;
  47. ss << t;
  48. return ss.str();
  49. }
  50. // Avoid char types used as character data.
  51. template<> inline std::string NumToString<signed char>(signed char t) {
  52. return NumToString(static_cast<int>(t));
  53. }
  54. template<> inline std::string NumToString<unsigned char>(unsigned char t) {
  55. return NumToString(static_cast<int>(t));
  56. }
  57. // Special versions for floats/doubles.
  58. template<> inline std::string NumToString<double>(double t) {
  59. // to_string() prints different numbers of digits for floats depending on
  60. // platform and isn't available on Android, so we use stringstream
  61. std::stringstream ss;
  62. // Use std::fixed to surpress scientific notation.
  63. ss << std::fixed << t;
  64. auto s = ss.str();
  65. // Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
  66. auto p = s.find_last_not_of('0');
  67. if (p != std::string::npos) {
  68. s.resize(p + 1); // Strip trailing zeroes.
  69. if (s[s.size() - 1] == '.')
  70. s.erase(s.size() - 1, 1); // Strip '.' if a whole number.
  71. }
  72. return s;
  73. }
  74. template<> inline std::string NumToString<float>(float t) {
  75. return NumToString(static_cast<double>(t));
  76. }
  77. // Convert an integer value to a hexadecimal string.
  78. // The returned string length is always xdigits long, prefixed by 0 digits.
  79. // For example, IntToStringHex(0x23, 8) returns the string "00000023".
  80. inline std::string IntToStringHex(int i, int xdigits) {
  81. std::stringstream ss;
  82. ss << std::setw(xdigits)
  83. << std::setfill('0')
  84. << std::hex
  85. << std::uppercase
  86. << i;
  87. return ss.str();
  88. }
  89. // Portable implementation of strtoll().
  90. inline int64_t StringToInt(const char *str, char **endptr = nullptr, int base = 10) {
  91. #ifdef _MSC_VER
  92. return _strtoi64(str, endptr, base);
  93. #else
  94. return strtoll(str, endptr, base);
  95. #endif
  96. }
  97. // Portable implementation of strtoull().
  98. inline int64_t StringToUInt(const char *str, char **endptr = nullptr, int base = 10) {
  99. #ifdef _MSC_VER
  100. return _strtoui64(str, endptr, base);
  101. #else
  102. return strtoull(str, endptr, base);
  103. #endif
  104. }
  105. typedef bool (*LoadFileFunction)(const char *filename, bool binary,
  106. std::string *dest);
  107. typedef bool (*FileExistsFunction)(const char *filename);
  108. LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
  109. FileExistsFunction SetFileExistsFunction(FileExistsFunction
  110. file_exists_function);
  111. // Check if file "name" exists.
  112. bool FileExists(const char *name);
  113. // Check if "name" exists and it is also a directory.
  114. bool DirExists(const char *name);
  115. // Load file "name" into "buf" returning true if successful
  116. // false otherwise. If "binary" is false data is read
  117. // using ifstream's text mode, otherwise data is read with
  118. // no transcoding.
  119. bool LoadFile(const char *name, bool binary, std::string *buf);
  120. // Save data "buf" of length "len" bytes into a file
  121. // "name" returning true if successful, false otherwise.
  122. // If "binary" is false data is written using ifstream's
  123. // text mode, otherwise data is written with no
  124. // transcoding.
  125. inline bool SaveFile(const char *name, const char *buf, size_t len,
  126. bool binary) {
  127. std::ofstream ofs(name, binary ? std::ofstream::binary : std::ofstream::out);
  128. if (!ofs.is_open()) return false;
  129. ofs.write(buf, len);
  130. return !ofs.bad();
  131. }
  132. // Save data "buf" into file "name" returning true if
  133. // successful, false otherwise. If "binary" is false
  134. // data is written using ifstream's text mode, otherwise
  135. // data is written with no transcoding.
  136. inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
  137. return SaveFile(name, buf.c_str(), buf.size(), binary);
  138. }
  139. // Functionality for minimalistic portable path handling:
  140. static const char kPosixPathSeparator = '/';
  141. #ifdef _WIN32
  142. static const char kPathSeparator = '\\';
  143. static const char *PathSeparatorSet = "\\/"; // Intentionally no ':'
  144. #else
  145. static const char kPathSeparator = kPosixPathSeparator;
  146. static const char *PathSeparatorSet = "/";
  147. #endif // _WIN32
  148. // Returns the path with the extension, if any, removed.
  149. inline std::string StripExtension(const std::string &filepath) {
  150. size_t i = filepath.find_last_of(".");
  151. return i != std::string::npos ? filepath.substr(0, i) : filepath;
  152. }
  153. // Returns the extension, if any.
  154. inline std::string GetExtension(const std::string &filepath) {
  155. size_t i = filepath.find_last_of(".");
  156. return i != std::string::npos ? filepath.substr(i + 1) : "";
  157. }
  158. // Return the last component of the path, after the last separator.
  159. inline std::string StripPath(const std::string &filepath) {
  160. size_t i = filepath.find_last_of(PathSeparatorSet);
  161. return i != std::string::npos ? filepath.substr(i + 1) : filepath;
  162. }
  163. // Strip the last component of the path + separator.
  164. inline std::string StripFileName(const std::string &filepath) {
  165. size_t i = filepath.find_last_of(PathSeparatorSet);
  166. return i != std::string::npos ? filepath.substr(0, i) : "";
  167. }
  168. // Concatenates a path with a filename, regardless of wether the path
  169. // ends in a separator or not.
  170. inline std::string ConCatPathFileName(const std::string &path,
  171. const std::string &filename) {
  172. std::string filepath = path;
  173. if (path.length() && path[path.size() - 1] != kPathSeparator &&
  174. path[path.size() - 1] != kPosixPathSeparator)
  175. filepath += kPathSeparator;
  176. filepath += filename;
  177. return filepath;
  178. }
  179. // This function ensure a directory exists, by recursively
  180. // creating dirs for any parts of the path that don't exist yet.
  181. inline void EnsureDirExists(const std::string &filepath) {
  182. auto parent = StripFileName(filepath);
  183. if (parent.length()) EnsureDirExists(parent);
  184. #ifdef _WIN32
  185. (void)_mkdir(filepath.c_str());
  186. #else
  187. mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
  188. #endif
  189. }
  190. // Obtains the absolute path from any other path.
  191. // Returns the input path if the absolute path couldn't be resolved.
  192. inline std::string AbsolutePath(const std::string &filepath) {
  193. #ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
  194. return filepath;
  195. #else
  196. #ifdef _WIN32
  197. char abs_path[MAX_PATH];
  198. #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
  199. return _fullpath(abs_path, filepath.c_str(), MAX_PATH)
  200. #else
  201. return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
  202. #endif
  203. #else
  204. char abs_path[PATH_MAX];
  205. return realpath(filepath.c_str(), abs_path)
  206. #endif
  207. ? abs_path
  208. : filepath;
  209. #endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
  210. }
  211. // To and from UTF-8 unicode conversion functions
  212. // Convert a unicode code point into a UTF-8 representation by appending it
  213. // to a string. Returns the number of bytes generated.
  214. inline int ToUTF8(uint32_t ucc, std::string *out) {
  215. assert(!(ucc & 0x80000000)); // Top bit can't be set.
  216. // 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
  217. for (int i = 0; i < 6; i++) {
  218. // Max bits this encoding can represent.
  219. uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i);
  220. if (ucc < (1u << max_bits)) { // does it fit?
  221. // Remaining bits not encoded in the first byte, store 6 bits each
  222. uint32_t remain_bits = i * 6;
  223. // Store first byte:
  224. (*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
  225. (ucc >> remain_bits));
  226. // Store remaining bytes:
  227. for (int j = i - 1; j >= 0; j--) {
  228. (*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
  229. }
  230. return i + 1; // Return the number of bytes added.
  231. }
  232. }
  233. assert(0); // Impossible to arrive here.
  234. return -1;
  235. }
  236. // Converts whatever prefix of the incoming string corresponds to a valid
  237. // UTF-8 sequence into a unicode code. The incoming pointer will have been
  238. // advanced past all bytes parsed.
  239. // returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in
  240. // this case).
  241. inline int FromUTF8(const char **in) {
  242. int len = 0;
  243. // Count leading 1 bits.
  244. for (int mask = 0x80; mask >= 0x04; mask >>= 1) {
  245. if (**in & mask) {
  246. len++;
  247. } else {
  248. break;
  249. }
  250. }
  251. if ((**in << len) & 0x80) return -1; // Bit after leading 1's must be 0.
  252. if (!len) return *(*in)++;
  253. // UTF-8 encoded values with a length are between 2 and 4 bytes.
  254. if (len < 2 || len > 4) {
  255. return -1;
  256. }
  257. // Grab initial bits of the code.
  258. int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
  259. for (int i = 0; i < len - 1; i++) {
  260. if ((**in & 0xC0) != 0x80) return -1; // Upper bits must 1 0.
  261. ucc <<= 6;
  262. ucc |= *(*in)++ & 0x3F; // Grab 6 more bits of the code.
  263. }
  264. // UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
  265. // UTF-16 surrogate pairs).
  266. if (ucc >= 0xD800 && ucc <= 0xDFFF) {
  267. return -1;
  268. }
  269. // UTF-8 must represent code points in their shortest possible encoding.
  270. switch (len) {
  271. case 2:
  272. // Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
  273. if (ucc < 0x0080 || ucc > 0x07FF) {
  274. return -1;
  275. }
  276. break;
  277. case 3:
  278. // Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
  279. if (ucc < 0x0800 || ucc > 0xFFFF) {
  280. return -1;
  281. }
  282. break;
  283. case 4:
  284. // Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
  285. if (ucc < 0x10000 || ucc > 0x10FFFF) {
  286. return -1;
  287. }
  288. break;
  289. }
  290. return ucc;
  291. }
  292. // Wraps a string to a maximum length, inserting new lines where necessary. Any
  293. // existing whitespace will be collapsed down to a single space. A prefix or
  294. // suffix can be provided, which will be inserted before or after a wrapped
  295. // line, respectively.
  296. inline std::string WordWrap(const std::string in, size_t max_length,
  297. const std::string wrapped_line_prefix,
  298. const std::string wrapped_line_suffix) {
  299. std::istringstream in_stream(in);
  300. std::string wrapped, line, word;
  301. in_stream >> word;
  302. line = word;
  303. while (in_stream >> word) {
  304. if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) <
  305. max_length) {
  306. line += " " + word;
  307. } else {
  308. wrapped += line + wrapped_line_suffix + "\n";
  309. line = wrapped_line_prefix + word;
  310. }
  311. }
  312. wrapped += line;
  313. return wrapped;
  314. }
  315. } // namespace flatbuffers
  316. #endif // FLATBUFFERS_UTIL_H_