You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by yu...@apache.org on 2025/04/15 05:10:45 UTC
(opendal) 01/01: feat(bindings/c): add support for read_range
This is an automated email from the ASF dual-hosted git repository.
yuchanns pushed a commit to branch binding-go-reader-at
in repository https://gitbox.apache.org/repos/asf/opendal.git
commit ec3a616d67fa2eadb7babe1b9ab0843d49c1e078
Author: Hanchin Hsieh <me...@yuchanns.xyz>
AuthorDate: Tue Apr 15 13:10:31 2025 +0800
feat(bindings/c): add support for read_range
---
bindings/c/README.md | 17 +++++++++++
bindings/c/include/opendal.h | 50 +++++++++++++++++++++++++++++++
bindings/c/src/operator.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++
bindings/c/tests/bdd.cpp | 8 +++++
4 files changed, 146 insertions(+)
diff --git a/bindings/c/README.md b/bindings/c/README.md
index abd7d97f3..e382f3ec7 100644
--- a/bindings/c/README.md
+++ b/bindings/c/README.md
@@ -84,6 +84,23 @@ sudo apt-get install cmake
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
+For Fedora:
+
+```shell
+# install C/C++ toolchain
+sudo dnf groupinstall "Development Tools" "Development Libraries"
+sudo dnf install gcc-c++
+
+# install clang-format
+sudo dnf install clang-tools-extra
+
+# install and build GTest library
+sudo dnf install gtest-devel
+
+# install CMake
+sudo dnf install cmake
+```
+
## Makefile
- To **build the library and header file**.
diff --git a/bindings/c/include/opendal.h b/bindings/c/include/opendal.h
index 73953d04e..e5b7f02d6 100644
--- a/bindings/c/include/opendal.h
+++ b/bindings/c/include/opendal.h
@@ -863,6 +863,56 @@ struct opendal_error *opendal_operator_write(const struct opendal_operator *op,
struct opendal_result_read opendal_operator_read(const struct opendal_operator *op,
const char *path);
+/**
+ * \brief Blocking read a range of data from `path`.
+ *
+ * Read a range of data from `path` blocking by operator. The range starts from `offset`
+ * with size of `size`.
+ *
+ * @param op The opendal_operator created previously
+ * @param path The path you want to read the data out
+ * @param offset The start position of the range to read
+ * @param size The size of the range to read
+ * @see opendal_operator
+ * @see opendal_result_read
+ * @see opendal_error
+ * @return Returns opendal_result_read, the `data` field is a pointer to a newly allocated
+ * opendal_bytes containing the range of data, the `error` field contains the error. If the
+ * `error` is not NULL, then the operation failed and the `data` field contains empty bytes.
+ *
+ * \note If the read operation succeeds, the returned opendal_bytes is newly allocated on heap.
+ * After your usage of that, please call opendal_bytes_free() to free the space.
+ *
+ * # Example
+ *
+ * Following is an example
+ * ```C
+ * // ... you have write "Hello, World!" to path "/testpath"
+ *
+ * // Read 5 bytes starting from offset 0
+ * opendal_result_read r = opendal_operator_read_range(op, "/testpath", 0, 5);
+ * assert(r.error == NULL);
+ *
+ * opendal_bytes bytes = r.data;
+ * assert(bytes.len == 5);
+ * opendal_bytes_free(&bytes);
+ * ```
+ *
+ * # Safety
+ *
+ * It is **safe** under the cases below
+ * * The memory pointed to by `path` must contain a valid nul terminator at the end of
+ * the string.
+ *
+ * # Panic
+ *
+ * * If the `path` points to NULL, this function panics, i.e. exits with information
+ */
+struct opendal_result_read opendal_operator_read_range(const struct opendal_operator *op,
+ const char *path,
+ uint64_t offset,
+ uint64_t size);
+
/**
* \brief Blocking read the data from `path`.
*
diff --git a/bindings/c/src/operator.rs b/bindings/c/src/operator.rs
index 84751fc49..64e86ced2 100644
--- a/bindings/c/src/operator.rs
+++ b/bindings/c/src/operator.rs
@@ -295,6 +295,77 @@ pub unsafe extern "C" fn opendal_operator_read(
}
}
+/// \brief Blocking read a range of data from `path`.
+///
+/// Read a range of data from `path` blocking by operator. The range starts from `offset`
+/// with size of `size`.
+///
+/// @param op The opendal_operator created previously
+/// @param path The path you want to read the data out
+/// @param offset The start position of the range to read
+/// @param size The size of the range to read
+/// @see opendal_operator
+/// @see opendal_result_read
+/// @see opendal_error
+/// @return Returns opendal_result_read, the `data` field is a pointer to a newly allocated
+/// opendal_bytes containing the range of data, the `error` field contains the error. If the
+/// `error` is not NULL, then the operation failed and the `data` field contains empty bytes.
+///
+/// \note If the read operation succeeds, the returned opendal_bytes is newly allocated on heap.
+/// After your usage of that, please call opendal_bytes_free() to free the space.
+///
+/// # Example
+///
+/// Following is an example
+/// ```C
+/// // ... you have write "Hello, World!" to path "/testpath"
+///
+/// // Read 5 bytes starting from offset 0
+/// opendal_result_read r = opendal_operator_read_range(op, "/testpath", 0, 5);
+/// assert(r.error == NULL);
+///
+/// opendal_bytes bytes = r.data;
+/// assert(bytes.len == 5);
+/// opendal_bytes_free(&bytes);
+/// ```
+///
+/// # Safety
+///
+/// It is **safe** under the cases below
+/// * The memory pointed to by `path` must contain a valid nul terminator at the end of
+/// the string.
+///
+/// # Panic
+///
+/// * If the `path` points to NULL, this function panics, i.e. exits with information
+#[no_mangle]
+pub unsafe extern "C" fn opendal_operator_read_range(
+ op: &opendal_operator,
+ path: *const c_char,
+ offset: u64,
+ size: u64,
+) -> opendal_result_read {
+ assert!(!path.is_null());
+ let path = std::ffi::CStr::from_ptr(path)
+ .to_str()
+ .expect("malformed path");
+ match op
+ .deref()
+ .read_with(path)
+ .range(offset..offset + size)
+ .call()
+ {
+ Ok(b) => opendal_result_read {
+ data: opendal_bytes::new(b),
+ error: std::ptr::null_mut(),
+ },
+ Err(e) => opendal_result_read {
+ data: opendal_bytes::empty(),
+ error: opendal_error::new(e),
+ },
+ }
+}
+
/// \brief Blocking read the data from `path`.
///
/// Read the data out from `path` blocking by operator, returns
diff --git a/bindings/c/tests/bdd.cpp b/bindings/c/tests/bdd.cpp
index 93b514845..1957ed721 100644
--- a/bindings/c/tests/bdd.cpp
+++ b/bindings/c/tests/bdd.cpp
@@ -93,6 +93,14 @@ TEST_F(OpendalBddTest, FeatureTest)
EXPECT_EQ(this->content[i], (char)(r.data.data[i]));
}
+ // The blocking file "test" must have content "Hello"
+ struct opendal_result_read r2 = opendal_operator_read_range(this->p, this->path.c_str(), 0, 5);
+ EXPECT_EQ(r2.error, nullptr);
+ EXPECT_EQ(r2.data.len, 5);
+ for (int i = 0; i < r2.data.len; i++) {
+ EXPECT_EQ(this->content[i], (char)(r2.data.data[i]));
+ }
+
// The blocking file should be deleted
error = opendal_operator_delete(this->p, this->path.c_str());
EXPECT_EQ(error, nullptr);