1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 #include <cstring> 16 17 #include "tensorflow/lite/toco/toco_port.h" 18 #include "tensorflow/lite/toco/toco_types.h" 19 #include "tensorflow/core/lib/core/errors.h" 20 #include "tensorflow/core/lib/core/status.h" 21 #include "tensorflow/core/platform/logging.h" 22 23 #if defined(__ANDROID__) && defined(__ARM_ARCH_7A__) 24 namespace std { 25 double round(double x) { return ::round(x); } 26 } // namespace std 27 #endif 28 29 namespace toco { 30 namespace port { 31 void CopyToBuffer(const string& src, char* dest) { 32 memcpy(dest, src.data(), src.size()); 33 } 34 35 #ifdef PLATFORM_GOOGLE 36 void CopyToBuffer(const Cord& src, char* dest) { src.CopyToArray(dest); } 37 #endif 38 } // namespace port 39 } // namespace toco 40 41 #if defined(PLATFORM_GOOGLE) && !defined(__APPLE__) && \ 42 !defined(__ANDROID__) && !defined(_WIN32) 43 44 // Wrap Google file operations. 45 46 #include "base/init_google.h" 47 #include "file/base/file.h" 48 #include "file/base/filesystem.h" 49 #include "file/base/helpers.h" 50 #include "file/base/options.h" 51 #include "file/base/path.h" 52 53 namespace toco { 54 namespace port { 55 56 void InitGoogle(const char* usage, int* argc, char*** argv, bool remove_flags) { 57 ::InitGoogle(usage, argc, argv, remove_flags); 58 } 59 60 void InitGoogleWasDoneElsewhere() { 61 // Nothing need be done since ::CheckInitGoogleIsDone() is aware of other 62 // possible initialization entry points. 63 } 64 65 void CheckInitGoogleIsDone(const char* message) { 66 ::CheckInitGoogleIsDone(message); 67 } 68 69 namespace file { 70 71 // Conversion to our wrapper Status. 72 tensorflow::Status ToStatus(const ::util::Status& uts) { 73 if (!uts.ok()) { 74 return tensorflow::Status( 75 tensorflow::errors::Code(::util::RetrieveErrorCode(uts)), 76 uts.error_message()); 77 } 78 return tensorflow::Status::OK(); 79 } 80 81 // Conversion to our wrapper Options. 82 toco::port::file::Options ToOptions(const ::file::Options& options) { 83 CHECK_EQ(&options, &::file::Defaults()); 84 return Options(); 85 } 86 87 tensorflow::Status Writable(const string& filename) { 88 File* f = nullptr; 89 const auto status = ::file::Open(filename, "w", &f, ::file::Defaults()); 90 if (f) { 91 QCHECK_OK(f->Close(::file::Defaults())); 92 } 93 return ToStatus(status); 94 } 95 96 tensorflow::Status Readable(const string& filename, 97 const file::Options& options) { 98 return ToStatus(::file::Readable(filename, ::file::Defaults())); 99 } 100 101 tensorflow::Status Exists(const string& filename, 102 const file::Options& options) { 103 auto status = ::file::Exists(filename, ::file::Defaults()); 104 return ToStatus(status); 105 } 106 107 tensorflow::Status GetContents(const string& filename, string* contents, 108 const file::Options& options) { 109 return ToStatus(::file::GetContents(filename, contents, ::file::Defaults())); 110 } 111 112 tensorflow::Status SetContents(const string& filename, const string& contents, 113 const file::Options& options) { 114 return ToStatus(::file::SetContents(filename, contents, ::file::Defaults())); 115 } 116 117 string JoinPath(const string& a, const string& b) { 118 return ::file::JoinPath(a, b); 119 } 120 121 } // namespace file 122 } // namespace port 123 } // namespace toco 124 125 #else // !PLATFORM_GOOGLE || __APPLE__ || __ANDROID__ || _WIN32 126 127 #include <fcntl.h> 128 #if defined(_WIN32) 129 #include <io.h> // for _close, _open, _read 130 #endif 131 #include <sys/stat.h> 132 #include <sys/types.h> 133 #include <unistd.h> 134 #include <cstdio> 135 136 #if defined(PLATFORM_GOOGLE) 137 #include "base/commandlineflags.h" 138 #endif 139 140 namespace toco { 141 namespace port { 142 143 #if defined(_WIN32) 144 #define close _close 145 #define open _open 146 #define read _read 147 // Windows does not support the same set of file permissions as other platforms, 148 // and also requires an explicit flag for binary file read/write support. 149 constexpr int kFileCreateMode = _S_IREAD | _S_IWRITE; 150 constexpr int kFileReadFlags = _O_RDONLY | _O_BINARY; 151 constexpr int kFileWriteFlags = _O_WRONLY | _O_BINARY | _O_CREAT; 152 #else 153 constexpr int kFileCreateMode = 0664; 154 constexpr int kFileReadFlags = O_RDONLY; 155 constexpr int kFileWriteFlags = O_CREAT | O_WRONLY; 156 #endif // _WIN32 157 158 static bool port_initialized = false; 159 160 void InitGoogleWasDoneElsewhere() { port_initialized = true; } 161 162 void InitGoogle(const char* usage, int* argc, char*** argv, bool remove_flags) { 163 if (!port_initialized) { 164 #if defined(PLATFORM_GOOGLE) 165 ParseCommandLineFlags(argc, argv, remove_flags); 166 #endif 167 port_initialized = true; 168 } 169 } 170 171 void CheckInitGoogleIsDone(const char* message) { 172 CHECK(port_initialized) << message; 173 } 174 175 namespace file { 176 177 tensorflow::Status Writable(const string& filename) { 178 FILE* f = fopen(filename.c_str(), "w"); 179 if (f) { 180 fclose(f); 181 return tensorflow::Status::OK(); 182 } 183 return tensorflow::errors::NotFound("not writable"); 184 } 185 186 tensorflow::Status Readable(const string& filename, 187 const file::Options& options) { 188 FILE* f = fopen(filename.c_str(), "r"); 189 if (f) { 190 fclose(f); 191 return tensorflow::Status::OK(); 192 } 193 return tensorflow::errors::NotFound("not readable"); 194 } 195 196 tensorflow::Status Exists(const string& filename, 197 const file::Options& options) { 198 struct stat statbuf; 199 int ret = stat(filename.c_str(), &statbuf); 200 if (ret == -1) { 201 return tensorflow::errors::NotFound("file doesn't exist"); 202 } 203 return tensorflow::Status::OK(); 204 } 205 206 tensorflow::Status GetContents(const string& path, string* output, 207 const file::Options& options) { 208 output->clear(); 209 210 int fd = open(path.c_str(), kFileReadFlags); 211 if (fd == -1) { 212 return tensorflow::errors::NotFound("can't open() for read"); 213 } 214 215 // Direct read, for speed. 216 const int kBufSize = 1 << 16; 217 char buffer[kBufSize]; 218 while (true) { 219 int size = read(fd, buffer, kBufSize); 220 if (size == 0) { 221 // Done. 222 close(fd); 223 return tensorflow::Status::OK(); 224 } else if (size == -1) { 225 // Error. 226 close(fd); 227 return tensorflow::errors::Internal("error during read()"); 228 } else { 229 output->append(buffer, size); 230 } 231 } 232 233 CHECK(0); 234 return tensorflow::errors::Internal("internal error"); 235 } 236 237 tensorflow::Status SetContents(const string& filename, const string& contents, 238 const file::Options& options) { 239 int fd = open(filename.c_str(), kFileWriteFlags, kFileCreateMode); 240 if (fd == -1) { 241 return tensorflow::errors::Internal("can't open() for write"); 242 } 243 244 size_t i = 0; 245 while (i < contents.size()) { 246 size_t to_write = contents.size() - i; 247 ssize_t written = write(fd, &contents[i], to_write); 248 if (written == -1) { 249 close(fd); 250 return tensorflow::errors::Internal("write() error"); 251 } 252 i += written; 253 } 254 close(fd); 255 256 return tensorflow::Status::OK(); 257 } 258 259 string JoinPath(const string& base, const string& filename) { 260 if (base.empty()) return filename; 261 string base_fixed = base; 262 if (!base_fixed.empty() && base_fixed.back() == '/') base_fixed.pop_back(); 263 string filename_fixed = filename; 264 if (!filename_fixed.empty() && filename_fixed.front() == '/') 265 filename_fixed.erase(0, 1); 266 return base_fixed + "/" + filename_fixed; 267 } 268 269 } // namespace file 270 } // namespace port 271 } // namespace toco 272 273 #endif // !PLATFORM_GOOGLE || __APPLE || __ANDROID__ || _WIN32 274