• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright 2016 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  
17  // clang-format off
18  // Dont't remove `format off`, it prevent reordering of win-includes.
19  #ifdef _WIN32
20  #  ifndef WIN32_LEAN_AND_MEAN
21  #    define WIN32_LEAN_AND_MEAN
22  #  endif
23  #  ifndef NOMINMAX
24  #    define NOMINMAX
25  #  endif
26  #  include <windows.h>  // Must be included before <direct.h>
27  #  include <direct.h>
28  #  include <winbase.h>
29  #  undef interface  // This is also important because of reasons
30  #else
31  #  include <limits.h>
32  #endif
33  // clang-format on
34  
35  #include "flatbuffers/base.h"
36  #include "flatbuffers/util.h"
37  
38  #include <sys/stat.h>
39  #include <clocale>
40  #include <fstream>
41  
42  namespace flatbuffers {
43  
FileExistsRaw(const char * name)44  bool FileExistsRaw(const char *name) {
45    std::ifstream ifs(name);
46    return ifs.good();
47  }
48  
LoadFileRaw(const char * name,bool binary,std::string * buf)49  bool LoadFileRaw(const char *name, bool binary, std::string *buf) {
50    if (DirExists(name)) return false;
51    std::ifstream ifs(name, binary ? std::ifstream::binary : std::ifstream::in);
52    if (!ifs.is_open()) return false;
53    if (binary) {
54      // The fastest way to read a file into a string.
55      ifs.seekg(0, std::ios::end);
56      auto size = ifs.tellg();
57      (*buf).resize(static_cast<size_t>(size));
58      ifs.seekg(0, std::ios::beg);
59      ifs.read(&(*buf)[0], (*buf).size());
60    } else {
61      // This is slower, but works correctly on all platforms for text files.
62      std::ostringstream oss;
63      oss << ifs.rdbuf();
64      *buf = oss.str();
65    }
66    return !ifs.bad();
67  }
68  
69  static LoadFileFunction g_load_file_function = LoadFileRaw;
70  static FileExistsFunction g_file_exists_function = FileExistsRaw;
71  
LoadFile(const char * name,bool binary,std::string * buf)72  bool LoadFile(const char *name, bool binary, std::string *buf) {
73    FLATBUFFERS_ASSERT(g_load_file_function);
74    return g_load_file_function(name, binary, buf);
75  }
76  
FileExists(const char * name)77  bool FileExists(const char *name) {
78    FLATBUFFERS_ASSERT(g_file_exists_function);
79    return g_file_exists_function(name);
80  }
81  
DirExists(const char * name)82  bool DirExists(const char *name) {
83    // clang-format off
84  
85    #ifdef _WIN32
86      #define flatbuffers_stat _stat
87      #define FLATBUFFERS_S_IFDIR _S_IFDIR
88    #else
89      #define flatbuffers_stat stat
90      #define FLATBUFFERS_S_IFDIR S_IFDIR
91    #endif
92    // clang-format on
93    struct flatbuffers_stat file_info;
94    if (flatbuffers_stat(name, &file_info) != 0) return false;
95    return (file_info.st_mode & FLATBUFFERS_S_IFDIR) != 0;
96  }
97  
SetLoadFileFunction(LoadFileFunction load_file_function)98  LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function) {
99    LoadFileFunction previous_function = g_load_file_function;
100    g_load_file_function = load_file_function ? load_file_function : LoadFileRaw;
101    return previous_function;
102  }
103  
SetFileExistsFunction(FileExistsFunction file_exists_function)104  FileExistsFunction SetFileExistsFunction(
105      FileExistsFunction file_exists_function) {
106    FileExistsFunction previous_function = g_file_exists_function;
107    g_file_exists_function =
108        file_exists_function ? file_exists_function : FileExistsRaw;
109    return previous_function;
110  }
111  
SaveFile(const char * name,const char * buf,size_t len,bool binary)112  bool SaveFile(const char *name, const char *buf, size_t len, bool binary) {
113    std::ofstream ofs(name, binary ? std::ofstream::binary : std::ofstream::out);
114    if (!ofs.is_open()) return false;
115    ofs.write(buf, len);
116    return !ofs.bad();
117  }
118  
119  // We internally store paths in posix format ('/'). Paths supplied
120  // by the user should go through PosixPath to ensure correct behavior
121  // on Windows when paths are string-compared.
122  
123  static const char kPathSeparatorWindows = '\\';
124  static const char *PathSeparatorSet = "\\/";  // Intentionally no ':'
125  
StripExtension(const std::string & filepath)126  std::string StripExtension(const std::string &filepath) {
127    size_t i = filepath.find_last_of(".");
128    return i != std::string::npos ? filepath.substr(0, i) : filepath;
129  }
130  
GetExtension(const std::string & filepath)131  std::string GetExtension(const std::string &filepath) {
132    size_t i = filepath.find_last_of(".");
133    return i != std::string::npos ? filepath.substr(i + 1) : "";
134  }
135  
StripPath(const std::string & filepath)136  std::string StripPath(const std::string &filepath) {
137    size_t i = filepath.find_last_of(PathSeparatorSet);
138    return i != std::string::npos ? filepath.substr(i + 1) : filepath;
139  }
140  
StripFileName(const std::string & filepath)141  std::string StripFileName(const std::string &filepath) {
142    size_t i = filepath.find_last_of(PathSeparatorSet);
143    return i != std::string::npos ? filepath.substr(0, i) : "";
144  }
145  
ConCatPathFileName(const std::string & path,const std::string & filename)146  std::string ConCatPathFileName(const std::string &path,
147                                 const std::string &filename) {
148    std::string filepath = path;
149    if (filepath.length()) {
150      char &filepath_last_character = string_back(filepath);
151      if (filepath_last_character == kPathSeparatorWindows) {
152        filepath_last_character = kPathSeparator;
153      } else if (filepath_last_character != kPathSeparator) {
154        filepath += kPathSeparator;
155      }
156    }
157    filepath += filename;
158    // Ignore './' at the start of filepath.
159    if (filepath[0] == '.' && filepath[1] == kPathSeparator) {
160      filepath.erase(0, 2);
161    }
162    return filepath;
163  }
164  
PosixPath(const char * path)165  std::string PosixPath(const char *path) {
166    std::string p = path;
167    std::replace(p.begin(), p.end(), '\\', '/');
168    return p;
169  }
170  
EnsureDirExists(const std::string & filepath)171  void EnsureDirExists(const std::string &filepath) {
172    auto parent = StripFileName(filepath);
173    if (parent.length()) EnsureDirExists(parent);
174      // clang-format off
175  
176    #ifdef _WIN32
177      (void)_mkdir(filepath.c_str());
178    #else
179      mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
180    #endif
181    // clang-format on
182  }
183  
AbsolutePath(const std::string & filepath)184  std::string AbsolutePath(const std::string &filepath) {
185    // clang-format off
186  
187    #ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
188      return filepath;
189    #else
190      #ifdef _WIN32
191        char abs_path[MAX_PATH];
192        return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
193      #else
194        char abs_path[PATH_MAX];
195        return realpath(filepath.c_str(), abs_path)
196      #endif
197        ? abs_path
198        : filepath;
199    #endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
200    // clang-format on
201  }
202  
203  // Locale-independent code.
204  #if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && \
205      (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
206  
207  // clang-format off
208  // Allocate locale instance at startup of application.
209  ClassicLocale ClassicLocale::instance_;
210  
211  #ifdef _MSC_VER
ClassicLocale()212    ClassicLocale::ClassicLocale()
213      : locale_(_create_locale(LC_ALL, "C")) {}
~ClassicLocale()214    ClassicLocale::~ClassicLocale() { _free_locale(locale_); }
215  #else
ClassicLocale()216    ClassicLocale::ClassicLocale()
217      : locale_(newlocale(LC_ALL, "C", nullptr)) {}
~ClassicLocale()218    ClassicLocale::~ClassicLocale() { freelocale(locale_); }
219  #endif
220  // clang-format on
221  
222  #endif  // !FLATBUFFERS_LOCALE_INDEPENDENT
223  
RemoveStringQuotes(const std::string & s)224  std::string RemoveStringQuotes(const std::string &s) {
225    auto ch = *s.c_str();
226    return ((s.size() >= 2) && (ch == '\"' || ch == '\'') &&
227            (ch == string_back(s)))
228               ? s.substr(1, s.length() - 2)
229               : s;
230  }
231  
SetGlobalTestLocale(const char * locale_name,std::string * _value)232  bool SetGlobalTestLocale(const char *locale_name, std::string *_value) {
233    const auto the_locale = setlocale(LC_ALL, locale_name);
234    if (!the_locale) return false;
235    if (_value) *_value = std::string(the_locale);
236    return true;
237  }
ReadEnvironmentVariable(const char * var_name,std::string * _value)238  bool ReadEnvironmentVariable(const char *var_name, std::string *_value) {
239    #ifdef _MSC_VER
240    __pragma(warning(disable : 4996)); // _CRT_SECURE_NO_WARNINGS
241    #endif
242    auto env_str = std::getenv(var_name);
243    if (!env_str) return false;
244    if (_value) *_value = std::string(env_str);
245    return true;
246  }
247  
248  }  // namespace flatbuffers
249