Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bindings/C): add support for list in C binding #2448

Merged
merged 18 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 24 additions & 26 deletions bindings/c/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
# Contributing
- [Contributing](#contributing)
- [Setup](#setup)
- [Using a dev container environment](#using-a-dev-container-environment)
- [Bring your own toolbox](#bring-your-own-toolbox)
- [Build](#build)
- [Test](#test)
- [Docs](#docs)
- [Misc](#misc)

1. [Contributing](#contributing)
1. [Setup](#setup)
1. [Using a dev container environment](#using-a-dev-container-environment)
2. [Bring your own toolbox](#bring-your-own-toolbox)
2. [Build](#build)
3. [Test](#test)
4. [Documentation](#documentation)

## Setup

### Using a dev container environment

OpenDAL provides a pre-configured [dev container](https://containers.dev/) that could be used in [Github Codespaces](https://github.com/features/codespaces), [VSCode](https://code.visualstudio.com/), [JetBrains](https://www.jetbrains.com/remote-development/gateway/), [JuptyerLab](https://jupyterlab.readthedocs.io/en/stable/). Please pick up your favourite runtime environment.

The fastest way is:

[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/apache/incubator-opendal?quickstart=1&machine=standardLinux32gb)

### Bring your own toolbox

To build OpenDAL C binding, the following is all you need:
- **A C++ compiler** that supports **c++14**, *e.g.* clang++ and g++

- **A C++ compiler** that supports **c++14**, _e.g._ clang++ and g++

- To format the code, you need to install **clang-format**
- The `opendal.h` is not formatted by hands when you contribute, please do not format the file. **Use `make format` only.**
- If your contribution is related to the files under `./tests`, you may format it before submitting your pull request. But notice that different versions of `clang-format` may format the files differently.

- The `opendal.h` is not formatted by hands when you contribute, please do not format the file. **Use `make format` only.**
- If your contribution is related to the files under `./tests`, you may format it before submitting your pull request. But notice that different versions of `clang-format` may format the files differently.

- **GTest(Google Test)** need to be installed to build the BDD (Behavior Driven Development) tests. To see how to build, check [here](https://github.com/google/googletest).

For Ubuntu and Debian:

```shell
# install C/C++ toolchain
sudo apt install -y build-essential
Expand All @@ -46,43 +51,36 @@ sudo ln -s /usr/lib/libgtest_main.a /usr/local/lib/libgtest_main.a
```

## Build

To build the library and header file.

```shell
make build
```

- The header file `opendal.h` is under `./include`
- The header file `opendal.h` is under `./include`
- The library is under `../../target/debug` after building.

To clean the build results.

```shell
make clean
```

## Test

To build and run the tests. (Note that you need to install GTest)

```shell
make test
```

```text
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from OpendalBddTest
[ RUN ] OpendalBddTest.FeatureTest
[ OK ] OpendalBddTest.FeatureTest (0 ms)
[----------] 1 test from OpendalBddTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
```

## Documentation

The documentation index page source is under `./docs/doxygen/html/index.html`.
If you want to build the documentations yourself, you could use

```sh
# this requires you to install doxygen
make doc
```

2 changes: 2 additions & 0 deletions bindings/c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ build:
.PHONY: test
test:
$(CXX) tests/bdd.cpp -o $(OBJ_DIR)/bdd $(CXXFLAGS) $(LDFLAGS) $(LIBS)
$(CXX) tests/list.cpp -o $(OBJ_DIR)/list $(CXXFLAGS) $(LDFLAGS) $(LIBS)
$(OBJ_DIR)/bdd
$(OBJ_DIR)/list

.PHONY: doc
doc:
Expand Down
19 changes: 12 additions & 7 deletions bindings/c/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
![](https://github.com/apache/incubator-opendal/assets/5351546/87bbf6e5-f19e-449a-b368-3e283016c887)

## Example

A simple read and write example

```C
#include "assert.h"
#include "opendal.h"
Expand Down Expand Up @@ -44,21 +46,25 @@ int main()
opendal_operator_free(&op);
}
```

For more examples, please refer to `./examples`

## Prerequisites

To build OpenDAL C binding, the following is all you need:
- **A C++ compiler** that supports **c++14**, *e.g.* clang++ and g++

- **A C++ compiler** that supports **c++14**, _e.g._ clang++ and g++

- To format the code, you need to install **clang-format**
- The `opendal.h` is not formatted by hands when you contribute, please do not format the file. **Use `make format` only.**
- If your contribution is related to the files under `./tests`, you may format it before submitting your pull request. But notice that different versions of `clang-format` may format the files differently.

- The `opendal.h` is not formatted by hands when you contribute, please do not format the file. **Use `make format` only.**
- If your contribution is related to the files under `./tests`, you may format it before submitting your pull request. But notice that different versions of `clang-format` may format the files differently.

- **GTest(Google Test)** need to be installed to build the BDD (Behavior Driven Development) tests. To see how to build, check [here](https://github.com/google/googletest).
- (optional) **Doxygen** need to be installed to generate documentations.

For Ubuntu and Debian:

```shell
# install C/C++ toolchain
sudo apt install -y build-essential
Expand All @@ -77,6 +83,7 @@ sudo ln -s /usr/lib/libgtest_main.a /usr/local/lib/libgtest_main.a
```

## Makefile

- To **build the library and header file**.

```sh
Expand All @@ -87,7 +94,6 @@ sudo ln -s /usr/lib/libgtest_main.a /usr/local/lib/libgtest_main.a

- The library is under `../../target/debug` after building.


- To **clean** the build results.

```sh
Expand All @@ -106,17 +112,16 @@ sudo ln -s /usr/lib/libgtest_main.a /usr/local/lib/libgtest_main.a
make examples
```



## Documentation

The documentation index page source is under `./docs/doxygen/html/index.html`.
If you want to build the documentations yourself, you could use

```sh
# this requires you to install doxygen
make doc
```


## License

[Apache v2.0](https://www.apache.org/licenses/LICENSE-2.0)
135 changes: 135 additions & 0 deletions bindings/c/include/opendal.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ typedef enum opendal_code {
OPENDAL_IS_SAME_FILE,
} opendal_code;

/**
* BlockingLister is designed to list entries at given path in a blocking
* manner.
*
* Users can construct Lister by `blocking_list` or `blocking_scan`.
*/
typedef struct BlockingLister BlockingLister;

/**
* BlockingOperator is the entry for all public blocking APIs.
*
Expand Down Expand Up @@ -113,6 +121,11 @@ typedef enum opendal_code {
*/
typedef struct BlockingOperator BlockingOperator;

/**
* Entry is the file/dir entry returned by `Lister`.
*/
typedef struct Entry Entry;

typedef struct HashMap_String__String HashMap_String__String;

/**
Expand Down Expand Up @@ -261,6 +274,43 @@ typedef struct opendal_result_stat {
enum opendal_code code;
} opendal_result_stat;

/**
* \brief BlockingLister is designed to list entries at given path in a blocking
* manner.
*
* Users can construct Lister by `blocking_list` or `blocking_scan`(currently not supported in C binding)
*
* For examples, please see the comment section of opendal_operator_blocking_list()
* @see opendal_operator_blocking_list()
*/
typedef struct opendal_blocking_lister {
struct BlockingLister *inner;
} opendal_blocking_lister;

/**
* \brief The result type returned by opendal_operator_blocking_list().
*
* The result type for opendal_operator_blocking_list(), the field `lister` contains the lister
* of the path, which is an iterator of the objects under the path. the field `code` represents
* whether the stat operation is successful.
*/
typedef struct opendal_result_list {
struct opendal_blocking_lister *lister;
enum opendal_code code;
} opendal_result_list;

/**
* \brief opendal_list_entry is the entry under a path, which is listed from the opendal_blocking_lister
*
* For examples, please see the comment section of opendal_operator_blocking_list()
* @see opendal_operator_blocking_list()
* @see opendal_list_entry_path()
* @see opendal_list_entry_name()
*/
typedef struct opendal_list_entry {
struct Entry *inner;
} opendal_list_entry;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
Expand Down Expand Up @@ -531,6 +581,56 @@ struct opendal_result_is_exist opendal_operator_is_exist(const struct opendal_op
struct opendal_result_stat opendal_operator_stat(const struct opendal_operator_ptr *ptr,
const char *path);

/**
* \brief Blockingly list the objects in `path`.
*
* List the object in `path` blockingly by `op_ptr`, return a result with a
* opendal_blocking_lister. Users should call opendal_lister_next() on the
* lister.
*
* @param ptr The opendal_operator_ptr created previously
* @param path The designated path you want to delete
* @see opendal_blocking_lister
* @return
*
* # Example
*
* Following is an example
* ```C
* // You have written some data into some files path "root/dir1"
* // Your opendal_operator_ptr was called ptr
* opendal_result_list l = opendal_operator_blocking_list(ptr, "root/dir1");
* assert(l.code == OPENDAL_OK);
*
* opendal_blocking_lister *lister = l.lister;
* opendal_list_entry *entry;
*
* while ((entry = opendal_lister_next(lister)) != NULL) {
* const char* de_path = opendal_list_entry_path(entry);
* const char* de_name = opendal_list_entry_name(entry);
* // ...... your operations
*
* // remember to free the entry after you are done using it
* opendal_list_entry_free(entry);
* }
*
* // and remember to free the lister
* opendal_lister_free(lister);
* ```
*
* # 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_list opendal_operator_blocking_list(const struct opendal_operator_ptr *ptr,
const char *path);

/**
* \brief Free the heap-allocated operator pointed by opendal_operator_ptr.
*
Expand Down Expand Up @@ -648,6 +748,41 @@ void opendal_operator_options_set(struct opendal_operator_options *self,
*/
void opendal_operator_options_free(const struct opendal_operator_options *options);

/**
* \brief Return the next object to be listed
*
* Lister is an iterator of the objects under its path, this method is the same as
* calling next() on the iterator
*
* For examples, please see the comment section of opendal_operator_blocking_list()
* @see opendal_operator_blocking_list()
*/
struct opendal_list_entry *opendal_lister_next(const struct opendal_blocking_lister *self);

/**
* \brief Free the heap-allocated metadata used by opendal_blocking_lister
*/
void opendal_lister_free(const struct opendal_blocking_lister *p);

/**
* Path of entry. Path is relative to operator's root.
* Only valid in current operator.
*/
const char *opendal_list_entry_path(const struct opendal_list_entry *self);

/**
* Name of entry. Name is the last segment of path.
*
* If this entry is a dir, `Name` MUST endswith `/`
* Otherwise, `Name` MUST NOT endswith `/`.
*/
const char *opendal_list_entry_name(const struct opendal_list_entry *self);

/**
* \brief Frees the heap memory used by the opendal_list_entry
*/
void opendal_list_entry_free(const struct opendal_list_entry *p);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
Expand Down
Loading