bindings/cpp/include/opendal.hpp (109 lines of code) (raw):
/*
* 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.
*/
#pragma once
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
#include "boost/iostreams/concepts.hpp"
#include "boost/iostreams/stream.hpp"
#include "data_structure.hpp"
namespace opendal {
namespace ffi {
class Operator;
class Reader;
class Lister;
} // namespace ffi
class Reader;
class Lister;
/**
* @class Operator
* @brief Operator is the entry for all public APIs.
*/
class Operator {
public:
Operator() noexcept;
/**
* @brief Construct a new Operator object
*
* @param scheme The scheme of the operator, same as the name of rust doc
* @param config The configuration of the operator, same as the service doc
*/
Operator(std::string_view scheme,
const std::unordered_map<std::string, std::string> &config = {});
// Disable copy and assign
Operator(const Operator &) = delete;
Operator &operator=(const Operator &) = delete;
// Enable move
Operator(Operator &&other) noexcept;
Operator &operator=(Operator &&other) noexcept;
~Operator() noexcept;
/**
* @brief Check if the operator is available
*
* @return true if the operator is available, false otherwise
*/
bool available() const;
/**
* @brief Read data from the operator
* @note The operation will make unnecessary copy. So we recommend to use the
* `reader` method.
*
* @param path The path of the data
* @return The data read from the operator
*/
std::string read(std::string_view path);
/**
* @brief Write data to the operator
*
* @param path The path of the data
* @param data The data to write
*/
void write(std::string_view path, std::string_view data);
/**
* @brief Read data from the operator
*
* @param path The path of the data
* @return The reader of the data
*/
Reader reader(std::string_view path);
/**
* @brief Check if the path exists
*
* @param path The path to check
* @return true if the path exists, false otherwise
*/
[[deprecated("Use exists() instead.")]]
bool is_exist(std::string_view path);
/**
* @brief Check if the path exists
*
* @param path The path to check
* @return true if the path exists, false otherwise
*/
bool exists(std::string_view path);
/**
* @brief Create a directory
*
* @param path The path of the directory
*/
void create_dir(std::string_view path);
/**
* @brief Copy a file from src to dst.
*
* @param src The source path
* @param dst The destination path
*/
void copy(std::string_view src, std::string_view dst);
/**
* @brief Rename a file from src to dst.
*
* @param src The source path
* @param dst The destination path
*/
void rename(std::string_view src, std::string_view dst);
/**
* @brief Remove a file or directory
*
* @param path The path of the file or directory
*/
void remove(std::string_view path);
/**
* @brief Get the metadata of a file or directory
*
* @param path The path of the file or directory
* @return The metadata of the file or directory
*/
Metadata stat(std::string_view path);
/**
* @brief List the entries of a directory
* @note The returned entries are sorted by name.
*
* @param path The path of the directory
* @return The entries of the directory
*/
std::vector<Entry> list(std::string_view path);
Lister lister(std::string_view path);
private:
void destroy() noexcept;
ffi::Operator *operator_{nullptr};
};
/**
* @class Reader
* @brief Reader is designed to read data from the operator.
* @details It provides basic read and seek operations. If you want to use it
* like a stream, you can use `ReaderStream` instead.
* @code{.cpp}
* opendal::ReaderStream stream(operator.reader("path"));
* @endcode
*/
class Reader
: public boost::iostreams::device<boost::iostreams::input_seekable> {
public:
Reader(Reader &&other) noexcept;
~Reader() noexcept;
std::streamsize read(void *s, std::streamsize n);
std::streampos seek(std::streamoff off, std::ios_base::seekdir way);
private:
friend class Operator;
Reader(ffi::Reader *pointer) noexcept;
void destroy() noexcept;
ffi::Reader *reader_{nullptr};
};
// Boost IOStreams requires it to be copyable. So we need to use
// `reference_wrapper` in ReaderStream. More details can be seen at
// https://lists.boost.org/Archives/boost/2005/10/95939.php
/**
* @class ReaderStream
* @brief ReaderStream is a stream wrapper of Reader which can provide
* `iostream` interface. It will keep a Reader inside so that you can ignore the
* lifetime of original Reader.
*/
class ReaderStream
: public boost::iostreams::stream<boost::reference_wrapper<Reader>> {
public:
ReaderStream(Reader &&reader)
: boost::iostreams::stream<boost::reference_wrapper<Reader>>(
boost::ref(reader_)),
reader_(std::move(reader)) {}
private:
Reader reader_;
};
/**
* @class Lister
* @brief Lister is designed to list the entries of a directory.
* @details It provides next operation to get the next entry. You can also use
* it like an iterator.
* @code{.cpp}
* auto lister = operator.lister("dir/");
* for (const auto &entry : lister) {
* // Do something with entry
* }
* @endcode
*/
class Lister {
public:
Lister(Lister &&other) noexcept;
~Lister() noexcept;
/**
* @class ListerIterator
* @brief ListerIterator is an iterator of Lister.
* @note It's an undefined behavior to make multiple iterators from one
* Lister.
*/
class Iterator {
public:
using iterator_category = std::input_iterator_tag;
using value_type = Entry;
using difference_type = std::ptrdiff_t;
using pointer = Entry *;
using reference = Entry &;
Iterator(Lister &lister) : lister_{lister} {
current_entry_ = lister_.next();
}
Entry operator*() { return current_entry_.value(); }
Iterator &operator++() {
if (current_entry_) {
current_entry_ = lister_.next();
}
return *this;
}
bool operator!=(const Iterator &other) const {
return current_entry_ != std::nullopt ||
other.current_entry_ != std::nullopt;
}
protected:
// Only used for end iterator
Iterator(Lister &lister, bool /*end*/) noexcept : lister_(lister) {}
private:
friend class Lister;
Lister &lister_;
std::optional<Entry> current_entry_;
};
/**
* @brief Get the next entry of the lister
*
* @return The next entry of the lister
*/
std::optional<Entry> next();
Iterator begin() { return Iterator(*this); }
Iterator end() { return Iterator(*this, true); }
private:
friend class Operator;
Lister(ffi::Lister *pointer) noexcept;
void destroy() noexcept;
ffi::Lister *lister_{nullptr};
};
} // namespace opendal