Skip to content

Commit

Permalink
Merge pull request #115 from Peefy/feat-c-and-cpp-api
Browse files Browse the repository at this point in the history
feat: c and cpp API init version
  • Loading branch information
Peefy authored Jul 16, 2024
2 parents b1fc8c0 + c0c448a commit 240b13c
Show file tree
Hide file tree
Showing 21 changed files with 685 additions and 45,694 deletions.
1 change: 1 addition & 0 deletions c/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
build/
examples/ping_api
examples/exec_api
examples/validate_api
4 changes: 2 additions & 2 deletions c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ fmt:
find . -name '*.cpp' -exec clang-format -i --style=WebKit --verbose {} \;
find . -name '*.c' -exec clang-format -i --style=WebKit --verbose {} \;

.PHONY: cargo-build
cargo-cargo:
.PHONY: cargo
cargo:
cargo build -r

$(BUILD_DIR):
Expand Down
169 changes: 162 additions & 7 deletions c/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,183 @@
# KCL Artifact Library for C

This repo is under development, PRs welcome!

## Developing

**Prerequisites**

+ Make
+ C++ compiler with C++11 support
+ Cargo

Run the command to build KCL C Lib.

```shell
cargo build --release
make cargo
make
```

## Build Examples
## Formatting

```shell
make fmt
```

## Examples

Run the following command to build all example codes.

```shell
make examples
```

## Run Examples
+ ExecProgram

```c
#include <kcl_lib.h>

int exec_file(const char* file_str) {
uint8_t buffer[BUFFER_SIZE];
uint8_t result_buffer[BUFFER_SIZE];
size_t message_length;
bool status;
struct Buffer file = {
.buffer = file_str,
.len = strlen(file_str),
};
struct Buffer* files[] = { &file };
struct RepeatedString strs = { .repeated = &files[0], .index = 0, .max_size = 1 };
ExecProgram_Args args = ExecProgram_Args_init_zero;
args.k_filename_list.funcs.encode = encode_str_list;
args.k_filename_list.arg = &strs;

pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
status = pb_encode(&stream, ExecProgram_Args_fields, &args);
message_length = stream.bytes_written;

if (!status) {
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}

const char* api_str = "KclvmService.ExecProgram";
size_t result_length = call_native((const uint8_t*)api_str, strlen(api_str), buffer, message_length, result_buffer);
if (check_error_prefix(result_buffer)) {
printf("%s", result_buffer);
return 1;
}
pb_istream_t istream = pb_istream_from_buffer(result_buffer, result_length);

ExecProgram_Result result = ExecProgram_Result_init_default;

uint8_t yaml_value_buffer[BUFFER_SIZE] = { 0 };
result.yaml_result.arg = yaml_value_buffer;
result.yaml_result.funcs.decode = decode_string;

uint8_t json_value_buffer[BUFFER_SIZE] = { 0 };
result.json_result.arg = json_value_buffer;
result.json_result.funcs.decode = decode_string;

uint8_t err_value_buffer[BUFFER_SIZE] = { 0 };
result.err_message.arg = err_value_buffer;
result.err_message.funcs.decode = decode_string;

uint8_t log_value_buffer[BUFFER_SIZE] = { 0 };
result.log_message.arg = log_value_buffer;
result.log_message.funcs.decode = decode_string;

status = pb_decode(&istream, ExecProgram_Result_fields, &result);

if (!status) {
printf("Decoding failed: %s\n", PB_GET_ERROR(&istream));
return 1;
}

if (result.yaml_result.arg) {
printf("%s\n", (char*)result.yaml_result.arg);
}

return 0;
}

int main()
{
exec_file("./test_data/schema.k");
return 0;
}
```
Run the ExecProgram example.
```shell
./examples/exec_api
```

## Formatting
+ ValidateCode

```c
#include <kcl_lib.h>

int validate(const char* code_str, const char* data_str)
{
uint8_t buffer[BUFFER_SIZE];
uint8_t result_buffer[BUFFER_SIZE];
size_t message_length;
bool status;

ValidateCode_Args validate_args = ValidateCode_Args_init_zero;
validate_args.code.funcs.encode = encode_string;
validate_args.code.arg = (void*)code_str;
validate_args.data.funcs.encode = encode_string;
validate_args.data.arg = (void*)data_str;

pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
status = pb_encode(&stream, ValidateCode_Args_fields, &validate_args);
message_length = stream.bytes_written;

if (!status) {
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}

const char* api_str = "KclvmService.ValidateCode";
size_t result_length = call_native((const uint8_t*)api_str, strlen(api_str), buffer, message_length, result_buffer);
pb_istream_t istream = pb_istream_from_buffer(result_buffer, result_length);
ValidateCode_Result result = ValidateCode_Result_init_default;

result.err_message.funcs.decode = decode_string;
uint8_t value_buffer[BUFFER_SIZE] = { 0 };
result.err_message.arg = value_buffer;

status = pb_decode(&istream, ValidateCode_Result_fields, &result);

if (!status) {
printf("Decoding failed: %s\n", PB_GET_ERROR(&istream));
return 1;
}

printf("Validate Status: %d\n", result.success);
if (result.err_message.arg) {
printf("Validate Error Message: %s\n", (char*)result.err_message.arg);
}
return 0;
}

int main()
{
const char* code_str = "schema Person:\n"
" name: str\n"
" age: int\n"
" check:\n"
" 0 < age < 120\n";
const char* data_str = "{\"name\": \"Alice\", \"age\": 10}";
const char* error_data_str = "{\"name\": \"Alice\", \"age\": 1110}";
validate(code_str, data_str);
validate(code_str, error_data_str);
return 0;
}
```
Run the ValidateCode example.
```shell
make fmt
./examples/exec_api
```
18 changes: 11 additions & 7 deletions c/examples/exec_api.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#include <kcl_lib.h>

int main()
{
int exec_file(const char* file_str) {
uint8_t buffer[BUFFER_SIZE];
uint8_t result_buffer[BUFFER_SIZE];
size_t message_length;
bool status;
const char* file_str = "./test_data/schema.k";
struct Buffer file = {
.buffer = file_str,
.len = strlen(file_str),
Expand Down Expand Up @@ -35,22 +33,22 @@ int main()
pb_istream_t istream = pb_istream_from_buffer(result_buffer, result_length);

ExecProgram_Result result = ExecProgram_Result_init_default;
result.yaml_result.funcs.decode = decode_string;
result.json_result.funcs.decode = decode_string;
result.err_message.funcs.decode = decode_string;
result.log_message.funcs.decode = decode_string;

uint8_t yaml_value_buffer[BUFFER_SIZE] = { 0 };
result.yaml_result.arg = yaml_value_buffer;
result.yaml_result.funcs.decode = decode_string;

uint8_t json_value_buffer[BUFFER_SIZE] = { 0 };
result.json_result.arg = json_value_buffer;
result.json_result.funcs.decode = decode_string;

uint8_t err_value_buffer[BUFFER_SIZE] = { 0 };
result.err_message.arg = err_value_buffer;
result.err_message.funcs.decode = decode_string;

uint8_t log_value_buffer[BUFFER_SIZE] = { 0 };
result.log_message.arg = log_value_buffer;
result.log_message.funcs.decode = decode_string;

status = pb_decode(&istream, ExecProgram_Result_fields, &result);

Expand All @@ -65,3 +63,9 @@ int main()

return 0;
}

int main()
{
exec_file("./test_data/schema.k");
return 0;
}
17 changes: 11 additions & 6 deletions c/examples/ping_api.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include <kcl_lib.h>

int main()
{
int ping(const char* msg) {
uint8_t buffer[BUFFER_SIZE];
uint8_t result_buffer[BUFFER_SIZE];
size_t message_length;
Expand All @@ -10,8 +9,7 @@ int main()
Ping_Args ping_args = Ping_Args_init_zero;
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
ping_args.value.funcs.encode = encode_string;
const char* hello_str = "hello";
ping_args.value.arg = (void*)hello_str;
ping_args.value.arg = (void*)msg;

status = pb_encode(&stream, Ping_Args_fields, &ping_args);
message_length = stream.bytes_written;
Expand All @@ -25,12 +23,12 @@ int main()
size_t result_length = call_native((const uint8_t*)api_str, strlen(api_str), buffer, message_length, result_buffer);

pb_istream_t istream = pb_istream_from_buffer(result_buffer, result_length);
Ping_Args decoded_ping_args = Ping_Args_init_default;
Ping_Result decoded_ping_args = Ping_Result_init_default;
decoded_ping_args.value.funcs.decode = decode_string;
uint8_t value_buffer[BUFFER_SIZE] = { 0 };
decoded_ping_args.value.arg = value_buffer;

status = pb_decode(&istream, Ping_Args_fields, &decoded_ping_args);
status = pb_decode(&istream, Ping_Result_fields, &decoded_ping_args);

if (!status) {
printf("Decoding failed: %s\n", PB_GET_ERROR(&istream));
Expand All @@ -45,3 +43,10 @@ int main()

return 0;
}

int main()
{
ping("hello");
ping("world");
return 0;
}
60 changes: 60 additions & 0 deletions c/examples/validate_api.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <kcl_lib.h>

int validate(const char* code_str, const char* data_str)
{
uint8_t buffer[BUFFER_SIZE];
uint8_t result_buffer[BUFFER_SIZE];
size_t message_length;
bool status;

ValidateCode_Args validate_args = ValidateCode_Args_init_zero;
validate_args.code.funcs.encode = encode_string;
validate_args.code.arg = (void*)code_str;
validate_args.data.funcs.encode = encode_string;
validate_args.data.arg = (void*)data_str;

pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
status = pb_encode(&stream, ValidateCode_Args_fields, &validate_args);
message_length = stream.bytes_written;

if (!status) {
printf("Encoding failed: %s\n", PB_GET_ERROR(&stream));
return 1;
}

const char* api_str = "KclvmService.ValidateCode";
size_t result_length = call_native((const uint8_t*)api_str, strlen(api_str), buffer, message_length, result_buffer);
pb_istream_t istream = pb_istream_from_buffer(result_buffer, result_length);
ValidateCode_Result result = ValidateCode_Result_init_default;

result.err_message.funcs.decode = decode_string;
uint8_t value_buffer[BUFFER_SIZE] = { 0 };
result.err_message.arg = value_buffer;

status = pb_decode(&istream, ValidateCode_Result_fields, &result);

if (!status) {
printf("Decoding failed: %s\n", PB_GET_ERROR(&istream));
return 1;
}

printf("Validate Status: %d\n", result.success);
if (result.err_message.arg) {
printf("Validate Error Message: %s\n", (char*)result.err_message.arg);
}
return 0;
}

int main()
{
const char* code_str = "schema Person:\n"
" name: str\n"
" age: int\n"
" check:\n"
" 0 < age < 120\n";
const char* data_str = "{\"name\": \"Alice\", \"age\": 10}";
const char* error_data_str = "{\"name\": \"Alice\", \"age\": 1110}";
validate(code_str, data_str);
validate(code_str, error_data_str);
return 0;
}
4 changes: 2 additions & 2 deletions c/include/kcl_lib.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef _API_H
#define _API_H
#ifndef _KCL_LIB_H
#define _KCL_LIB_H

#ifdef __cplusplus
extern "C" {
Expand Down
2 changes: 2 additions & 0 deletions c/scripts/generate.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
git clone https://github.com/nanopb/nanopb.git
cd nanopb
grep -v '^package' ../../../spec/gpyrpc/spec.proto > "spec.proto"
sed -i '' -e 's|string default |string default_ |g' spec.proto

python3 generator/nanopb_generator.py spec.proto

# Copy headers
Expand Down
3 changes: 3 additions & 0 deletions cpp/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
Language: Cpp
BasedOnStyle: Google
12 changes: 12 additions & 0 deletions cpp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
*.swp
*.*~
.DS_Store

.vs/
.vscode

build/
compile_commands.json
.cache
build*
Cargo.lock
Loading

0 comments on commit 240b13c

Please sign in to comment.