| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 |
| * |
| * http://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 "iceberg/file_io.h" |
| |
| #include <limits> |
| #include <utility> |
| |
| #include "iceberg/util/macros.h" |
| |
| namespace iceberg { |
| |
| namespace { |
| |
| Status FinishWithCloseStatus(Status operation_status, Status close_status) { |
| if (!operation_status.has_value()) { |
| auto error = operation_status.error(); |
| if (!close_status.has_value()) { |
| error.message += "; additionally failed to close stream: "; |
| error.message += close_status.error().message; |
| } |
| return std::unexpected<Error>(std::move(error)); |
| } |
| return close_status; |
| } |
| |
| } // namespace |
| |
| Result<std::unique_ptr<InputFile>> FileIO::NewInputFile(std::string file_location) { |
| return NotImplemented("NewInputFile not implemented for {}", file_location); |
| } |
| |
| Result<std::unique_ptr<InputFile>> FileIO::NewInputFile(std::string file_location, |
| size_t /*length*/) { |
| return NewInputFile(std::move(file_location)); |
| } |
| |
| Result<std::unique_ptr<OutputFile>> FileIO::NewOutputFile(std::string file_location) { |
| return NotImplemented("NewOutputFile not implemented for {}", file_location); |
| } |
| |
| Result<std::string> FileIO::ReadFile(const std::string& file_location, |
| std::optional<size_t> length) { |
| int64_t read_size; |
| std::unique_ptr<InputFile> input_file; |
| if (length.has_value()) { |
| if (*length > static_cast<size_t>(std::numeric_limits<int64_t>::max())) { |
| return InvalidArgument("Requested read length {} exceeds int64_t max", *length); |
| } |
| ICEBERG_ASSIGN_OR_RAISE(input_file, NewInputFile(file_location, *length)); |
| read_size = static_cast<int64_t>(*length); |
| } else { |
| ICEBERG_ASSIGN_OR_RAISE(input_file, NewInputFile(file_location)); |
| ICEBERG_ASSIGN_OR_RAISE(read_size, input_file->Size()); |
| } |
| if (read_size < 0) { |
| return Invalid("Invalid negative file size {} for {}", read_size, file_location); |
| } |
| |
| auto size = static_cast<size_t>(read_size); |
| std::string content(size, '\0'); |
| ICEBERG_ASSIGN_OR_RAISE(auto stream, input_file->Open()); |
| Status read_status = {}; |
| if (size > 0) { |
| auto bytes = std::as_writable_bytes(std::span(content.data(), content.size())); |
| read_status = stream->ReadFully(/*position=*/0, bytes); |
| } |
| ICEBERG_RETURN_UNEXPECTED( |
| FinishWithCloseStatus(std::move(read_status), stream->Close())); |
| return content; |
| } |
| |
| Status FileIO::WriteFile(const std::string& file_location, std::string_view content) { |
| ICEBERG_ASSIGN_OR_RAISE(auto output_file, NewOutputFile(file_location)); |
| ICEBERG_ASSIGN_OR_RAISE(auto stream, output_file->CreateOrOverwrite()); |
| Status status = {}; |
| if (!content.empty()) { |
| auto bytes = std::as_bytes(std::span(content.data(), content.size())); |
| status = stream->Write(bytes); |
| } |
| if (status.has_value()) { |
| status = stream->Flush(); |
| } |
| return FinishWithCloseStatus(std::move(status), stream->Close()); |
| } |
| |
| Status FileIO::DeleteFiles(const std::vector<std::string>& file_locations) { |
| for (const auto& file_location : file_locations) { |
| ICEBERG_RETURN_UNEXPECTED(DeleteFile(file_location)); |
| } |
| return {}; |
| } |
| |
| } // namespace iceberg |