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/contrib/lite/toco/toco_port.h"
     18 #include "tensorflow/contrib/lite/toco/toco_types.h"
     19 #include "tensorflow/core/platform/logging.h"
     20 
     21 namespace toco {
     22 namespace port {
     23 void CopyToBuffer(const string& src, char* dest) {
     24   memcpy(dest, src.data(), src.size());
     25 }
     26 
     27 #ifdef PLATFORM_GOOGLE
     28 void CopyToBuffer(const Cord& src, char* dest) { src.CopyToArray(dest); }
     29 #endif
     30 }  // namespace port
     31 }  // namespace toco
     32 
     33 #if defined(PLATFORM_GOOGLE) && !defined(__APPLE__) && !defined(__ANDROID__)
     34 
     35 // Wrap Google file operations.
     36 
     37 #include "base/init_google.h"
     38 #include "file/base/file.h"
     39 #include "file/base/filesystem.h"
     40 #include "file/base/helpers.h"
     41 #include "file/base/options.h"
     42 #include "file/base/path.h"
     43 
     44 namespace toco {
     45 namespace port {
     46 
     47 void InitGoogle(const char* usage, int* argc, char*** argv, bool remove_flags) {
     48   ::InitGoogle(usage, argc, argv, remove_flags);
     49 }
     50 
     51 void CheckInitGoogleIsDone(const char* message) {
     52   ::CheckInitGoogleIsDone(message);
     53 }
     54 
     55 namespace file {
     56 
     57 // Conversion to our wrapper Status.
     58 Status ToStatus(const ::util::Status& uts) {
     59   return Status(uts.ok(), uts.error_message());
     60 }
     61 
     62 // Conversion to our wrapper Options.
     63 toco::port::file::Options ToOptions(const ::file::Options& options) {
     64   CHECK_EQ(&options, &::file::Defaults());
     65   return Options();
     66 }
     67 
     68 Status Writable(const string& filename) {
     69   File* f = nullptr;
     70   const auto status = ::file::Open(filename, "w", &f, ::file::Defaults());
     71   if (f) {
     72     QCHECK_OK(f->Close(::file::Defaults()));
     73   }
     74   return ToStatus(status);
     75 }
     76 
     77 Status Readable(const string& filename, const file::Options& options) {
     78   return ToStatus(::file::Readable(filename, ::file::Defaults()));
     79 }
     80 
     81 Status Exists(const string& filename, const file::Options& options) {
     82   auto status = ::file::Exists(filename, ::file::Defaults());
     83   return ToStatus(status);
     84 }
     85 
     86 Status GetContents(const string& filename, string* contents,
     87                    const file::Options& options) {
     88   return ToStatus(::file::GetContents(filename, contents, ::file::Defaults()));
     89 }
     90 
     91 Status SetContents(const string& filename, const string& contents,
     92                    const file::Options& options) {
     93   return ToStatus(::file::SetContents(filename, contents, ::file::Defaults()));
     94 }
     95 
     96 string JoinPath(const string& a, const string& b) {
     97   return ::file::JoinPath(a, b);
     98 }
     99 
    100 }  // namespace file
    101 }  // namespace port
    102 }  // namespace toco
    103 
    104 #else  // (__APPLE__ || __ANDROID__)
    105 
    106 #include <fcntl.h>
    107 #include <sys/stat.h>
    108 #include <sys/types.h>
    109 #include <unistd.h>
    110 #include <cstdio>
    111 
    112 #if defined(PLATFORM_GOOGLE)
    113 #include "base/commandlineflags.h"
    114 #endif
    115 
    116 namespace toco {
    117 namespace port {
    118 
    119 static bool port_initialized = false;
    120 
    121 void InitGoogle(const char* usage, int* argc, char*** argv, bool remove_flags) {
    122   if (!port_initialized) {
    123 #if defined(PLATFORM_GOOGLE)
    124     ParseCommandLineFlags(argc, argv, remove_flags);
    125 #endif
    126     port_initialized = true;
    127   }
    128 }
    129 
    130 void CheckInitGoogleIsDone(const char* message) {
    131   CHECK(port_initialized) << message;
    132 }
    133 
    134 namespace file {
    135 
    136 Status Writable(const string& filename) {
    137   FILE* f = fopen(filename.c_str(), "w");
    138   if (f) {
    139     fclose(f);
    140     return Status(true, "");
    141   }
    142   return Status(false, "not writable");
    143 }
    144 
    145 Status Readable(const string& filename, const file::Options& options) {
    146   FILE* f = fopen(filename.c_str(), "r");
    147   if (f) {
    148     fclose(f);
    149     return Status(true, "");
    150   }
    151   return Status(false, "not readable");
    152 }
    153 
    154 Status Exists(const string& filename, const file::Options& options) {
    155   struct stat statbuf;
    156   int ret = stat(filename.c_str(), &statbuf);
    157   return Status(ret != -1, "");
    158 }
    159 
    160 Status GetContents(const string& path, string* output,
    161                    const file::Options& options) {
    162   output->clear();
    163 
    164   int fd = open(path.c_str(), O_RDONLY);
    165   if (fd == -1) {
    166     return Status(false, "can't open() for read");
    167   }
    168 
    169   // Direct read, for speed.
    170   const int kBufSize = 1 << 16;
    171   char buffer[kBufSize];
    172   while (true) {
    173     int size = read(fd, buffer, kBufSize);
    174     if (size == 0) {
    175       // Done.
    176       close(fd);
    177       return Status(true, "");
    178     } else if (size == -1) {
    179       // Error.
    180       close(fd);
    181       return Status(false, "error during read()");
    182     } else {
    183       output->append(buffer, size);
    184     }
    185   }
    186 
    187   CHECK(0);
    188   return Status(false, "internal error");
    189 }
    190 
    191 Status SetContents(const string& filename, const string& contents,
    192                    const file::Options& options) {
    193   int fd = open(filename.c_str(), O_WRONLY | O_CREAT, 0664);
    194   if (fd == -1) {
    195     return Status(false, "can't open() for write");
    196   }
    197 
    198   size_t i = 0;
    199   while (i < contents.size()) {
    200     size_t to_write = contents.size() - i;
    201     ssize_t written = write(fd, &contents[i], to_write);
    202     if (written == -1) {
    203       close(fd);
    204       return Status(false, "write() error");
    205     }
    206     i += written;
    207   }
    208   close(fd);
    209 
    210   return Status(true, "");
    211 }
    212 
    213 string JoinPath(const string& base, const string& filename) {
    214   if (base.empty()) return filename;
    215   string base_fixed = base;
    216   if (!base_fixed.empty() && base_fixed.back() == '/') base_fixed.pop_back();
    217   string filename_fixed = filename;
    218   if (!filename_fixed.empty() && filename_fixed.front() == '/')
    219     filename_fixed.erase(0, 1);
    220   return base_fixed + "/" + filename_fixed;
    221 }
    222 
    223 }  // namespace file
    224 }  // namespace port
    225 }  // namespace toco
    226 
    227 #endif  // (__APPLE || __ANDROID__)
    228