util.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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 <stdlib.h>
  23. #include <assert.h>
  24. #ifdef _WIN32
  25. #ifndef WIN32_LEAN_AND_MEAN
  26. #define WIN32_LEAN_AND_MEAN
  27. #endif
  28. #ifndef NOMINMAX
  29. #define NOMINMAX
  30. #endif
  31. #include <windows.h>
  32. #include <winbase.h>
  33. #include <direct.h>
  34. #else
  35. #include <sys/stat.h>
  36. #include <limits.h>
  37. #endif
  38. namespace flatbuffers {
  39. // Convert an integer or floating point value to a string.
  40. // In contrast to std::stringstream, "char" values are
  41. // converted to a string of digits.
  42. template<typename T> std::string NumToString(T t) {
  43. // to_string() prints different numbers of digits for floats depending on
  44. // platform and isn't available on Android, so we use stringstream
  45. std::stringstream ss;
  46. ss << t;
  47. return ss.str();
  48. }
  49. // Avoid char types used as character data.
  50. template<> inline std::string NumToString<signed char>(signed char t) {
  51. return NumToString(static_cast<int>(t));
  52. }
  53. template<> inline std::string NumToString<unsigned char>(unsigned char t) {
  54. return NumToString(static_cast<int>(t));
  55. }
  56. // Convert an integer value to a hexadecimal string.
  57. // The returned string length is always xdigits long, prefixed by 0 digits.
  58. // For example, IntToStringHex(0x23, 8) returns the string "00000023".
  59. inline std::string IntToStringHex(int i, int xdigits) {
  60. std::stringstream ss;
  61. ss << std::setw(xdigits)
  62. << std::setfill('0')
  63. << std::hex
  64. << std::uppercase
  65. << i;
  66. return ss.str();
  67. }
  68. // Portable implementation of strtoull().
  69. inline int64_t StringToInt(const char *str, int base = 10) {
  70. #ifdef _MSC_VER
  71. return _strtoui64(str, nullptr, base);
  72. #else
  73. return strtoull(str, nullptr, base);
  74. #endif
  75. }
  76. // Load file "name" into "buf" returning true if successful
  77. // false otherwise. If "binary" is false data is read
  78. // using ifstream's text mode, otherwise data is read with
  79. // no transcoding.
  80. inline bool LoadFile(const char *name, bool binary, std::string *buf) {
  81. std::ifstream ifs(name, binary ? std::ifstream::binary : std::ifstream::in);
  82. if (!ifs.is_open()) return false;
  83. *buf = std::string(std::istreambuf_iterator<char>(ifs),
  84. std::istreambuf_iterator<char>());
  85. return !ifs.bad();
  86. }
  87. // Save data "buf" of length "len" bytes into a file
  88. // "name" returning true if successful, false otherwise.
  89. // If "binary" is false data is written using ifstream's
  90. // text mode, otherwise data is written with no
  91. // transcoding.
  92. inline bool SaveFile(const char *name, const char *buf, size_t len,
  93. bool binary) {
  94. std::ofstream ofs(name, binary ? std::ofstream::binary : std::ofstream::out);
  95. if (!ofs.is_open()) return false;
  96. ofs.write(buf, len);
  97. return !ofs.bad();
  98. }
  99. // Save data "buf" into file "name" returning true if
  100. // successful, false otherwise. If "binary" is false
  101. // data is written using ifstream's text mode, otherwise
  102. // data is written with no transcoding.
  103. inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
  104. return SaveFile(name, buf.c_str(), buf.size(), binary);
  105. }
  106. // Functionality for minimalistic portable path handling:
  107. static const char kPosixPathSeparator = '/';
  108. #ifdef _WIN32
  109. static const char kPathSeparator = '\\';
  110. static const char *PathSeparatorSet = "\\/"; // Intentionally no ':'
  111. #else
  112. static const char kPathSeparator = kPosixPathSeparator;
  113. static const char *PathSeparatorSet = "/";
  114. #endif // _WIN32
  115. // Returns the path with the extension, if any, removed.
  116. inline std::string StripExtension(const std::string &filepath) {
  117. size_t i = filepath.find_last_of(".");
  118. return i != std::string::npos ? filepath.substr(0, i) : filepath;
  119. }
  120. // Return the last component of the path, after the last separator.
  121. inline std::string StripPath(const std::string &filepath) {
  122. size_t i = filepath.find_last_of(PathSeparatorSet);
  123. return i != std::string::npos ? filepath.substr(i + 1) : filepath;
  124. }
  125. // Strip the last component of the path + separator.
  126. inline std::string StripFileName(const std::string &filepath) {
  127. size_t i = filepath.find_last_of(PathSeparatorSet);
  128. return i != std::string::npos ? filepath.substr(0, i) : "";
  129. }
  130. // Concatenates a path with a filename, regardless of wether the path
  131. // ends in a separator or not.
  132. inline std::string ConCatPathFileName(const std::string &path,
  133. const std::string &filename) {
  134. std::string filepath = path;
  135. if (path.length() && path.back() != kPathSeparator &&
  136. path.back() != kPosixPathSeparator)
  137. filepath += kPathSeparator;
  138. filepath += filename;
  139. return filepath;
  140. }
  141. // This function ensure a directory exists, by recursively
  142. // creating dirs for any parts of the path that don't exist yet.
  143. inline void EnsureDirExists(const std::string &filepath) {
  144. auto parent = StripFileName(filepath);
  145. if (parent.length()) EnsureDirExists(parent);
  146. #ifdef _WIN32
  147. _mkdir(filepath.c_str());
  148. #else
  149. mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
  150. #endif
  151. }
  152. // Obtains the absolute path from any other path.
  153. // Returns the input path if the absolute path couldn't be resolved.
  154. inline std::string AbsolutePath(const std::string &filepath) {
  155. #ifdef _WIN32
  156. char abs_path[MAX_PATH];
  157. #if defined(WP8) || defined(WINRT)
  158. return 0
  159. #else
  160. return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
  161. #endif
  162. #else
  163. char abs_path[PATH_MAX];
  164. return realpath(filepath.c_str(), abs_path)
  165. #endif
  166. ? abs_path
  167. : filepath;
  168. }
  169. // To and from UTF-8 unicode conversion functions
  170. // Convert a unicode code point into a UTF-8 representation by appending it
  171. // to a string. Returns the number of bytes generated.
  172. inline int ToUTF8(uint32_t ucc, std::string *out) {
  173. assert(!(ucc & 0x80000000)); // Top bit can't be set.
  174. // 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
  175. for (int i = 0; i < 6; i++) {
  176. // Max bits this encoding can represent.
  177. uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i);
  178. if (ucc < (1u << max_bits)) { // does it fit?
  179. // Remaining bits not encoded in the first byte, store 6 bits each
  180. uint32_t remain_bits = i * 6;
  181. // Store first byte:
  182. (*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
  183. (ucc >> remain_bits));
  184. // Store remaining bytes:
  185. for (int j = i - 1; j >= 0; j--) {
  186. (*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
  187. }
  188. return i + 1; // Return the number of bytes added.
  189. }
  190. }
  191. assert(0); // Impossible to arrive here.
  192. return -1;
  193. }
  194. // Converts whatever prefix of the incoming string corresponds to a valid
  195. // UTF-8 sequence into a unicode code. The incoming pointer will have been
  196. // advanced past all bytes parsed.
  197. // returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in
  198. // this case).
  199. inline int FromUTF8(const char **in) {
  200. int len = 0;
  201. // Count leading 1 bits.
  202. for (int mask = 0x80; mask >= 0x04; mask >>= 1) {
  203. if (**in & mask) {
  204. len++;
  205. } else {
  206. break;
  207. }
  208. }
  209. if ((**in << len) & 0x80) return -1; // Bit after leading 1's must be 0.
  210. if (!len) return *(*in)++;
  211. // Grab initial bits of the code.
  212. int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
  213. for (int i = 0; i < len - 1; i++) {
  214. if ((**in & 0xC0) != 0x80) return -1; // Upper bits must 1 0.
  215. ucc <<= 6;
  216. ucc |= *(*in)++ & 0x3F; // Grab 6 more bits of the code.
  217. }
  218. return ucc;
  219. }
  220. } // namespace flatbuffers
  221. #endif // FLATBUFFERS_UTIL_H_