/src/sentencepiece/src/filesystem.cc
Line | Count | Source |
1 | | // Copyright 2016 Google Inc. |
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 "filesystem.h" |
16 | | |
17 | | #include <cerrno> |
18 | | #include <fstream> |
19 | | #include <iostream> |
20 | | #include <memory> |
21 | | #include <string> |
22 | | |
23 | | #include "absl/log/log.h" |
24 | | #include "absl/status/status.h" |
25 | | #include "absl/strings/str_cat.h" |
26 | | #include "absl/strings/string_view.h" |
27 | | #include "util.h" |
28 | | |
29 | | #if defined(_WIN32) && !defined(__CYGWIN__) && defined(UNICODE) && \ |
30 | | defined(_UNICODE) |
31 | | #include <windows.h> |
32 | | namespace { |
33 | | std::wstring Utf8ToWide(absl::string_view input) { |
34 | | const int output_length = ::MultiByteToWideChar( |
35 | | CP_UTF8, 0, input.data(), static_cast<int>(input.size()), nullptr, 0); |
36 | | if (output_length == 0) { |
37 | | return L""; |
38 | | } |
39 | | std::wstring output(output_length, 0); |
40 | | const int result = ::MultiByteToWideChar(CP_UTF8, 0, input.data(), |
41 | | static_cast<int>(input.size()), |
42 | | output.data(), output.size()); |
43 | | return result == output_length ? output : L""; |
44 | | } |
45 | | } // namespace |
46 | | #define WPATH(path) (Utf8ToWide(path).c_str()) |
47 | | #else |
48 | 0 | #define WPATH(path) (path.data()) |
49 | | #endif |
50 | | |
51 | | namespace sentencepiece { |
52 | | namespace filesystem { |
53 | | |
54 | | class PosixReadableFile : public ReadableFile { |
55 | | public: |
56 | | explicit PosixReadableFile(absl::string_view filename, |
57 | 0 | bool is_binary = false) { |
58 | 0 | if (filename.empty()) { |
59 | 0 | is_ = &std::cin; |
60 | 0 | } else { |
61 | 0 | file_.open(WPATH(filename), |
62 | 0 | is_binary ? std::ios::binary | std::ios::in : std::ios::in); |
63 | 0 | is_ = &file_; |
64 | 0 | } |
65 | 0 | if (!*is_ || ((is_->peek() != 0) && is_->fail())) { |
66 | 0 | status_ = absl::ErrnoToStatus(errno, absl::StrCat("\"", filename, "\"")); |
67 | 0 | } |
68 | 0 | } |
69 | | |
70 | 0 | ~PosixReadableFile() override = default; |
71 | | |
72 | 0 | absl::Status status() const override { return status_; } |
73 | | |
74 | 0 | bool ReadLine(std::string* line) override { |
75 | 0 | return static_cast<bool>(std::getline(*is_, *line)); |
76 | 0 | } |
77 | | |
78 | 0 | bool ReadAll(std::string* line) override { |
79 | 0 | if (is_ == &std::cin) { |
80 | 0 | LOG(ERROR) << "ReadAll is not supported for stdin."; |
81 | 0 | return false; |
82 | 0 | } |
83 | 0 | line->assign(std::istreambuf_iterator<char>(*is_), |
84 | 0 | std::istreambuf_iterator<char>()); |
85 | 0 | return true; |
86 | 0 | } |
87 | | |
88 | | private: |
89 | | absl::Status status_; |
90 | | std::ifstream file_; |
91 | | std::istream* is_; |
92 | | }; |
93 | | |
94 | | class PosixWritableFile : public WritableFile { |
95 | | public: |
96 | | explicit PosixWritableFile(absl::string_view filename, |
97 | 0 | bool is_binary = false) { |
98 | 0 | if (filename.empty()) { |
99 | 0 | os_ = &std::cout; |
100 | 0 | } else { |
101 | 0 | file_.open(WPATH(filename), |
102 | 0 | is_binary ? std::ios::binary | std::ios::out : std::ios::out); |
103 | 0 | os_ = &file_; |
104 | 0 | } |
105 | 0 | if (!*os_) { |
106 | 0 | status_ = absl::ErrnoToStatus(errno, absl::StrCat("\"", filename, "\"")); |
107 | 0 | } |
108 | 0 | } |
109 | | |
110 | 0 | ~PosixWritableFile() override = default; |
111 | | |
112 | 0 | absl::Status status() const override { return status_; } |
113 | | |
114 | 0 | bool Write(absl::string_view text) override { |
115 | 0 | os_->write(text.data(), text.size()); |
116 | 0 | return os_->good(); |
117 | 0 | } |
118 | | |
119 | 0 | bool WriteLine(absl::string_view text) override { |
120 | 0 | return Write(text) && Write("\n"); |
121 | 0 | } |
122 | | |
123 | | private: |
124 | | absl::Status status_; |
125 | | std::ofstream file_; |
126 | | std::ostream* os_; |
127 | | }; |
128 | | |
129 | | using DefaultReadableFile = PosixReadableFile; |
130 | | using DefaultWritableFile = PosixWritableFile; |
131 | | |
132 | | std::unique_ptr<ReadableFile> NewReadableFile(absl::string_view filename, |
133 | 0 | bool is_binary) { |
134 | 0 | return std::make_unique<DefaultReadableFile>(filename, is_binary); |
135 | 0 | } |
136 | | |
137 | | std::unique_ptr<WritableFile> NewWritableFile(absl::string_view filename, |
138 | 0 | bool is_binary) { |
139 | 0 | return std::make_unique<DefaultWritableFile>(filename, is_binary); |
140 | 0 | } |
141 | | |
142 | | } // namespace filesystem |
143 | | } // namespace sentencepiece |