Home | History | Annotate | Download | only in toco
      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