diff --git a/internal/platform/implementation/windows/BUILD b/internal/platform/implementation/windows/BUILD index f402f637..5075cec1 100644 --- a/internal/platform/implementation/windows/BUILD +++ b/internal/platform/implementation/windows/BUILD @@ -60,6 +60,7 @@ cc_library( "bluetooth_classic_socket.h", "condition_variable.h", "executor.h", + "file.h", "mutex.h", "scheduled_executor.h", "server_sync.h", @@ -113,6 +114,7 @@ cc_library( "bluetooth_classic_server_socket.cc", "bluetooth_classic_socket.cc", "executor.cc", + "file.cc", "platform.cc", "scheduled_executor.cc", "submittable_executor.cc", diff --git a/internal/platform/implementation/windows/file.cc b/internal/platform/implementation/windows/file.cc new file mode 100644 index 00000000..df0aecb7 --- /dev/null +++ b/internal/platform/implementation/windows/file.cc @@ -0,0 +1,111 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "internal/platform/implementation/windows/file.h" + +#include +#include +#include +#include +#include + +#include "absl/memory/memory.h" +#include "absl/strings/string_view.h" +#include "internal/platform/exception.h" +#include "internal/platform/implementation/windows/utils.h" + +namespace location { +namespace nearby { +namespace windows { + +// InputFile +std::unique_ptr IOFile::CreateInputFile( + const absl::string_view file_path, size_t size) { + return absl::WrapUnique(new IOFile(file_path, size)); +} + +IOFile::IOFile(const absl::string_view file_path, size_t size) + : path_(file_path) { + // Always open input file path as wide string on Windows platform. + std::wstring wide_path = string_to_wstring(std::string(file_path)); + file_.open(wide_path, std::ios::binary | std::ios::in | std::ios::ate); + + total_size_ = file_.tellg(); + file_.seekg(0); +} + +std::unique_ptr IOFile::CreateOutputFile(const absl::string_view path) { + return std::unique_ptr(new IOFile(path)); +} + +IOFile::IOFile(const absl::string_view file_path) + : file_(), path_(file_path), total_size_(0) { + // Always open input file path as wide string on Windows platform. + std::wstring wide_path = string_to_wstring(path_); + file_.open(wide_path, std::ios::binary | std::ios::out); +} + +ExceptionOr IOFile::Read(std::int64_t size) { + if (!file_.is_open()) { + return ExceptionOr{Exception::kIo}; + } + + if (file_.peek() == EOF) { + return ExceptionOr{ByteArray{}}; + } + + if (!file_.good()) { + return ExceptionOr{Exception::kIo}; + } + + ByteArray bytes(size); + std::unique_ptr read_bytes{new char[size]}; + file_.read(read_bytes.get(), static_cast(size)); + auto num_bytes_read = file_.gcount(); + if (num_bytes_read == 0) { + return ExceptionOr{Exception::kIo}; + } + + return ExceptionOr(ByteArray(read_bytes.get(), num_bytes_read)); +} + +Exception IOFile::Close() { + if (file_.is_open()) { + file_.close(); + } + return {Exception::kSuccess}; +} + +Exception IOFile::Write(const ByteArray& data) { + if (!file_.is_open()) { + return {Exception::kIo}; + } + + if (!file_.good()) { + return {Exception::kIo}; + } + + file_.write(data.data(), data.size()); + file_.flush(); + return {file_.good() ? Exception::kSuccess : Exception::kIo}; +} + +Exception IOFile::Flush() { + file_.flush(); + return {file_.good() ? Exception::kSuccess : Exception::kIo}; +} + +} // namespace windows +} // namespace nearby +} // namespace location diff --git a/internal/platform/implementation/windows/file.h b/internal/platform/implementation/windows/file.h new file mode 100644 index 00000000..435ea333 --- /dev/null +++ b/internal/platform/implementation/windows/file.h @@ -0,0 +1,62 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PLATFORM_IMPL_WINDOWS_FILE_H_ +#define PLATFORM_IMPL_WINDOWS_FILE_H_ + +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "internal/platform/exception.h" +#include "internal/platform/implementation/input_file.h" +#include "internal/platform/implementation/output_file.h" + +namespace location { +namespace nearby { +namespace windows { + +class IOFile final : public api::InputFile, public api::OutputFile { + public: + static std::unique_ptr CreateInputFile( + const absl::string_view file_path, size_t size); + + static std::unique_ptr CreateOutputFile(const absl::string_view path); + + ExceptionOr Read(std::int64_t size) override; + + std::string GetFilePath() const override { return path_; } + + std::int64_t GetTotalSize() const override { return total_size_; } + Exception Close() override; + + Exception Write(const ByteArray& data) override; + Exception Flush() override; + + private: + explicit IOFile(const absl::string_view file_path, size_t size); + explicit IOFile(const absl::string_view file_path); + + std::fstream file_; + std::string path_; + std::int64_t total_size_; +}; + +} // namespace windows +} // namespace nearby +} // namespace location + +#endif // PLATFORM_IMPL_WINDOWS_FILE_H_ diff --git a/internal/platform/implementation/windows/platform.cc b/internal/platform/implementation/windows/platform.cc index a6ca28e7..f25afc7f 100644 --- a/internal/platform/implementation/windows/platform.cc +++ b/internal/platform/implementation/windows/platform.cc @@ -28,7 +28,6 @@ #include #include "internal/platform/implementation/shared/count_down_latch.h" -#include "internal/platform/implementation/shared/file.h" #include "internal/platform/implementation/windows/atomic_boolean.h" #include "internal/platform/implementation/windows/atomic_reference.h" #include "internal/platform/implementation/windows/ble.h" @@ -38,6 +37,7 @@ #include "internal/platform/implementation/windows/cancelable.h" #include "internal/platform/implementation/windows/condition_variable.h" #include "internal/platform/implementation/windows/executor.h" +#include "internal/platform/implementation/windows/file.h" #include "internal/platform/implementation/windows/future.h" #include "internal/platform/implementation/windows/listenable_future.h" #include "internal/platform/implementation/windows/log_message.h" @@ -46,6 +46,7 @@ #include "internal/platform/implementation/windows/server_sync.h" #include "internal/platform/implementation/windows/settable_future.h" #include "internal/platform/implementation/windows/submittable_executor.h" +#include "internal/platform/implementation/windows/utils.h" #include "internal/platform/implementation/windows/webrtc.h" #include "internal/platform/implementation/windows/wifi.h" #include "internal/platform/implementation/windows/wifi_hotspot.h" @@ -170,7 +171,10 @@ std::string CreateOutputFileWithRename(absl::string_view path) { std::string target(sanitized_path); std::fstream file; - file.open(target, std::fstream::binary | std::fstream::in); + + // Open file as std::wstring + file.open(windows::string_to_wstring(target), + std::fstream::binary | std::fstream::in); // While we successfully open the file, keep incrementing the count. while (!(file.rdstate() & std::ifstream::failbit)) { @@ -178,7 +182,8 @@ std::string CreateOutputFileWithRename(absl::string_view path) { #undef StrCat target = absl::StrCat(folder, file_name1, " (", ++count, ")", file_name2); file.clear(); - file.open(target, std::fstream::binary | std::fstream::in); + file.open(windows::string_to_wstring(target), + std::fstream::binary | std::fstream::in); } // The above leaves the file open, so close it. @@ -309,13 +314,13 @@ std::unique_ptr ImplementationPlatform::CreateInputFile( PayloadId payload_id, std::int64_t total_size) { std::string parent_folder(""); std::string file_name(std::to_string(payload_id)); - return shared::IOFile::CreateInputFile(GetDownloadPath(file_name), - total_size); + return windows::IOFile::CreateInputFile(GetDownloadPath(file_name), + total_size); } std::unique_ptr ImplementationPlatform::CreateInputFile( absl::string_view file_path, size_t size) { - return shared::IOFile::CreateInputFile(file_path, size); + return windows::IOFile::CreateInputFile(file_path, size); } ABSL_DEPRECATED("This interface will be deleted in the near future.") @@ -323,7 +328,7 @@ std::unique_ptr ImplementationPlatform::CreateOutputFile( PayloadId payload_id) { std::string parent_folder(""); std::string file_name(std::to_string(payload_id)); - return shared::IOFile::CreateOutputFile( + return windows::IOFile::CreateOutputFile( GetDownloadPath(parent_folder, file_name)); } @@ -342,7 +347,7 @@ std::unique_ptr ImplementationPlatform::CreateOutputFile( int result = SHCreateDirectoryExA(0, folder_path.data(), nullptr); } - return shared::IOFile::CreateOutputFile(file_path); + return windows::IOFile::CreateOutputFile(file_path); } // TODO(b/184975123): replace with real implementation.