diff --git a/.github/workflows/enforce-linking-issues.yml b/.github/workflows/enforce-linking-issues.yml deleted file mode 100644 index ebeddd9ee..000000000 --- a/.github/workflows/enforce-linking-issues.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: Enforce linking issues - -on: - pull_request_target: - types: [opened, edited, labeled] - -jobs: - main: - uses: eclipse-zenoh/zenoh/.github/workflows/enforce-linking-issues.yml@main - secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f633f9d71..7599b0ba4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,188 +14,160 @@ name: Release on: - release: - types: [published] schedule: - cron: "0 0 * * 1-5" workflow_dispatch: - + inputs: + live-run: + type: boolean + description: Live-run + required: false + version: + type: string + description: Release number + required: false jobs: - preps: - name: Preparation + tag: + name: Branch, Bump & tag runs-on: ubuntu-latest + outputs: + version: ${{ steps.create-release-branch.outputs.version }} + branch: ${{ steps.create-release-branch.outputs.branch }} steps: - - name: Clone this repository + - id: create-release-branch + uses: eclipse-zenoh/ci/create-release-branch@main + with: + repo: ${{ github.repository }} + live-run: ${{ inputs.live-run || false }} + # NOTE(fuzzypixelz): When the version is undefined (e.g. on schedule + # events) we cannot use git-describe as CMake doesn't support it. + # However, we still need some placeholder version to test that the + # version can be reliably bumped. + version: ${{ inputs.version || '0.0.0' }} + github-token: ${{ secrets.BOT_TOKEN_WORKFLOW }} + + - name: Checkout this repository uses: actions/checkout@v4 + with: + ref: ${{ steps.create-release-branch.outputs.branch }} + + - name: Bump and tag project + run: bash ci/scripts/bump-and-tag.bash + env: + VERSION: ${{ steps.create-release-branch.outputs.version }} + GIT_USER_NAME: eclipse-zenoh-bot + GIT_USER_EMAIL: eclipse-zenoh-bot@users.noreply.github.com - - name: Environment setup - id: env - shell: bash - run: | - echo "GITHUB_REF=${GITHUB_REF}" - echo "GITHUB_SHA=${GITHUB_SHA:0:8}" - GIT_BRANCH=`[[ $GITHUB_REF =~ ^refs/heads/.* ]] && echo ${GITHUB_REF/refs\/heads\//} || true` - echo "GIT_BRANCH=${GIT_BRANCH}" - echo "GIT_BRANCH=${GIT_BRANCH}" >> $GITHUB_OUTPUT - GIT_TAG=`[[ $GITHUB_REF =~ ^refs/tags/.* ]] && echo ${GITHUB_REF/refs\/tags\//} || true` - echo "GIT_TAG=${GIT_TAG}" - echo "GIT_TAG=${GIT_TAG}" >> $GITHUB_OUTPUT - - ZENOH_VERSION=$(sed -n 's/^project(libzenohpico VERSION \(.*\) LANGUAGES C)/\1/p' CMakeLists.txt | head -n1) - echo "ZENOH_VERSION=${ZENOH_VERSION}" - echo "ZENOH_VERSION=${ZENOH_VERSION}" >> $GITHUB_OUTPUT - if [ -n "${GIT_TAG}" ]; then - IS_RELEASE="true" - echo "IS_RELEASE=${IS_RELEASE}" - echo "IS_RELEASE=${IS_RELEASE}" >> $GITHUB_OUTPUT - PKG_VERSION=${GIT_TAG} - elif [ -n "${GIT_BRANCH}" ]; then - PKG_VERSION=${GIT_BRANCH}-${GITHUB_SHA:0:8} - else - PKG_VERSION=${ZENOH_VERSION}-${GITHUB_SHA:0:8} - fi - echo "PKG_VERSION=${PKG_VERSION}" - echo "PKG_VERSION=${PKG_VERSION}" >> $GITHUB_OUTPUT - - CROSSBUILD_TARGETS=$(sed -n 's/^CROSSBUILD_TARGETS=\(.*\)/\1/p' GNUmakefile | head -n1) - echo "CROSSBUILD_TARGETS=$CROSSBUILD_TARGETS" - TARGET_MATRIX="{\"target\": [\"${CROSSBUILD_TARGETS// /\",\"}\"]}" - echo "TARGET_MATRIX=$TARGET_MATRIX" - echo "TARGET_MATRIX=$TARGET_MATRIX" >> $GITHUB_OUTPUT + pre-build: + name: Pre-Build + needs: tag + runs-on: ubuntu-latest outputs: - GIT_BRANCH: ${{ steps.env.outputs.GIT_BRANCH }} - GIT_TAG: ${{ steps.env.outputs.GIT_TAG }} - IS_RELEASE: ${{ steps.env.outputs.IS_RELEASE }} - ZENOH_VERSION: ${{ steps.env.outputs.ZENOH_VERSION }} - PKG_VERSION: ${{ steps.env.outputs.PKG_VERSION }} - TARGET_MATRIX: ${{ steps.env.outputs.TARGET_MATRIX }} - - macos-build: - name: Build on macos-x64 - needs: preps + build-linux-matrix: ${{ steps.pre-build.outputs.build-linux-matrix }} + steps: + - name: Clone this repository + uses: actions/checkout@v4 + with: + ref: ${{ needs.tag.outputs.branch }} + + - id: pre-build + run: bash ci/scripts/pre-build.bash + + build-macos: + name: Build for macOS (x64) + needs: [tag, pre-build] runs-on: macos-latest steps: - name: Clone this repository uses: actions/checkout@v4 + with: + ref: ${{ needs.tag.outputs.branch }} - - name: MacOS build - run: make + - id: build-macos + run: bash ci/scripts/build-macos.bash env: - BUILD_TYPE: RELEASE - - - name: Packaging - id: package - shell: bash - run: | - LIB_PKG_NAME=${PWD}/zenoh-pico-${{ needs.preps.outputs.PKG_VERSION }}-macos-x64.zip - echo "Packaging ${LIB_PKG_NAME}:" - cd build && zip -r ${LIB_PKG_NAME} lib && cd - - zip -r ${LIB_PKG_NAME} include - echo "LIB_PKG_NAME=${LIB_PKG_NAME}" >> $GITHUB_OUTPUT - - EXP_PKG_NAME=${PWD}/zenoh-pico-${{ needs.preps.outputs.PKG_VERSION }}-macos-x64-examples.zip - echo "Packaging ${EXP_PKG_NAME}:" - cd build/examples && zip ${EXP_PKG_NAME} * && cd - - echo "EXP_PKG_NAME=${EXP_PKG_NAME}" >> $GITHUB_OUTPUT - - - name: "Upload x86_64 macos package" - uses: actions/upload-artifact@v3 + REPO: ${{ github.repository }} + VERSION: ${{ needs.tag.outputs.version }} + + - name: Upload macOS library archive + uses: actions/upload-artifact@v4 with: - name: macos-x64 - path: | - ${{ steps.package.outputs.LIB_PKG_NAME }} - ${{ steps.package.outputs.EXP_PKG_NAME }} + name: ${{ steps.build-macos.outputs.archive-lib }} + path: ${{ steps.build-macos.outputs.archive-lib }} - linux-builds: + - name: Upload macOS examples archive + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.build-macos.outputs.archive-examples }} + path: ${{ steps.build-macos.outputs.archive-examples }} + + build-linux: name: Crossbuild for ${{ matrix.target }} - needs: preps + needs: [tag, pre-build] runs-on: ubuntu-latest strategy: fail-fast: false - matrix: ${{fromJson(needs.preps.outputs.TARGET_MATRIX)}} + matrix: ${{ fromJson(needs.pre-build.outputs.build-linux-matrix) }} steps: - name: Clone this repository uses: actions/checkout@v4 + with: + ref: ${{ needs.tag.outputs.branch }} - - name: make for ${{ matrix.target }} + - id: build-linux + run: bash ci/scripts/build-linux.bash env: - BUILD_TYPE: RELEASE - run: make ${{ matrix.target }} - - - name: Packaging - id: package - shell: bash - run: | - TARGET=${{ matrix.target }} - LIB_PKG_NAME=${PWD}/zenoh-pico-${{ needs.preps.outputs.PKG_VERSION }}-${TARGET}.zip - DEB_PKG_NAME=${PWD}/zenoh-pico-${{ needs.preps.outputs.PKG_VERSION }}-${TARGET}-deb-pkgs.zip - RPM_PKG_NAME=${PWD}/zenoh-pico-${{ needs.preps.outputs.PKG_VERSION }}-${TARGET}-rpm-pkgs.zip - EXP_PKG_NAME=${PWD}/zenoh-pico-${{ needs.preps.outputs.PKG_VERSION }}-${TARGET}-examples.zip - - echo "Packaging ${LIB_PKG_NAME}:" - cd crossbuilds/${TARGET} && zip -r ${LIB_PKG_NAME} lib && cd - - zip -r ${LIB_PKG_NAME} include - echo "LIB_PKG_NAME=${LIB_PKG_NAME}" >> $GITHUB_OUTPUT - - cd crossbuilds/${TARGET}/packages - echo "Packaging ${DEB_PKG_NAME}:" - zip ${DEB_PKG_NAME} *.deb - echo "DEB_PKG_NAME=${DEB_PKG_NAME}" >> $GITHUB_OUTPUT - echo "Packaging ${RPM_PKG_NAME}:" - zip ${RPM_PKG_NAME} *.rpm - echo "RPM_PKG_NAME=${RPM_PKG_NAME}" >> $GITHUB_OUTPUT - cd - - - echo "Packaging ${EXP_PKG_NAME}:" - cd crossbuilds/${TARGET}/examples && zip ${EXP_PKG_NAME} * && cd - - echo "EXP_PKG_NAME=${EXP_PKG_NAME}" >> $GITHUB_OUTPUT - - - name: "Upload packages" - uses: actions/upload-artifact@v3 + REPO: ${{ github.repository }} + VERSION: ${{ needs.tag.outputs.version }} + TARGET: ${{ matrix.target }} + + - name: Upload Linux library archive for ${{ matrix.target }} + uses: actions/upload-artifact@v4 with: - name: ${{ matrix.target }} - path: | - ${{ steps.package.outputs.LIB_PKG_NAME }} - ${{ steps.package.outputs.DEB_PKG_NAME }} - ${{ steps.package.outputs.RPM_PKG_NAME }} - ${{ steps.package.outputs.EXP_PKG_NAME }} - - publication: - name: Publish the release - if: needs.preps.outputs.IS_RELEASE == 'true' - needs: [preps, macos-build, linux-builds] - runs-on: ubuntu-latest - steps: - - name: Download result of previous builds - uses: actions/download-artifact@v3 + name: ${{ steps.build-linux.outputs.archive-lib }} + path: ${{ steps.build-linux.outputs.archive-lib }} + + - name: Upload Linux examples archive for ${{ matrix.target }} + uses: actions/upload-artifact@v4 with: - path: ARTIFACTS + name: ${{ steps.build-linux.outputs.archive-examples }} + path: ${{ steps.build-linux.outputs.archive-examples }} - - name: Publish as github release - uses: softprops/action-gh-release@v1 + - name: Upload Linux RPM archive for ${{ matrix.target }} + uses: actions/upload-artifact@v4 with: - files: ARTIFACTS/*/*.* + name: ${{ steps.build-linux.outputs.archive-rpm }} + path: ${{ steps.build-linux.outputs.archive-rpm }} - - name: Publish to download.eclipse.org/zenoh - env: - SSH_TARGET: genie.zenoh@projects-storage.eclipse.org - ECLIPSE_BASE_DIR: /home/data/httpd/download.eclipse.org/zenoh/zenoh-pico - shell: bash - run: | - echo "--- setup ssh-agent" - eval "$(ssh-agent -s)" - echo 'echo "${{ secrets.SSH_PASSPHRASE }}"' > ~/.ssh_askpass && chmod +x ~/.ssh_askpass - echo "${{ secrets.SSH_PRIVATE_KEY }}" | tr -d '\r' | DISPLAY=NONE SSH_ASKPASS=~/.ssh_askpass ssh-add - > /dev/null 2>&1 - rm -f ~/.ssh_askpass - echo "--- test ssh:" - ssh -o "StrictHostKeyChecking=no" ${SSH_TARGET} ls -al - echo "---- list artifacts to upload:" - ls -R ARTIFACTS || true - DOWNLOAD_DIR=${ECLIPSE_BASE_DIR}/${{ needs.preps.outputs.PKG_VERSION }} - echo "---- copy artifacts into ${DOWNLOAD_DIR}" - ssh -o "StrictHostKeyChecking=no" ${SSH_TARGET} mkdir -p ${DOWNLOAD_DIR} - cd ARTIFACTS - sha256sum */* > sha256sums.txt - scp -o "StrictHostKeyChecking=no" -r * ${SSH_TARGET}:${DOWNLOAD_DIR}/ - echo "---- cleanup identity" - ssh-add -D + - name: Upload Linux DEB archive for ${{ matrix.target }} + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.build-linux.outputs.archive-deb }} + path: ${{ steps.build-linux.outputs.archive-deb }} + + eclipse: + needs: [tag, build-macos, build-linux] + runs-on: ubuntu-latest + steps: + - uses: eclipse-zenoh/ci/publish-crates-eclipse@main + with: + live-run: ${{ inputs.live-run || false }} + version: ${{ needs.tag.outputs.version }} + ssh-host: genie.zenoh@projects-storage.eclipse.org + ssh-host-path: /home/data/httpd/download.eclipse.org/zenoh/zenoh-pico + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + ssh-passphrase: ${{ secrets.SSH_PASSPHRASE }} + archive-patterns: '.*\.zip' + + github: + needs: [tag, build-macos, build-linux] + runs-on: ubuntu-latest + steps: + - uses: eclipse-zenoh/ci/publish-crates-github@main + with: + repo: ${{ github.repository }} + live-run: ${{ inputs.live-run || false }} + version: ${{ needs.tag.outputs.version }} + branch: ${{ needs.tag.outputs.branch }} + github-token: ${{ secrets.BOT_TOKEN_WORKFLOW }} + archive-patterns: '.*\.zip' diff --git a/.gitignore b/.gitignore index ae356975d..46661a4eb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # CMake build crossbuilds +CMakeFiles # vscode .vscode diff --git a/CMakeLists.txt b/CMakeLists.txt index 0da6badd7..7d35cb139 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,34 @@ # cmake_minimum_required(VERSION 3.13) -project(zenohpico VERSION 0.11.0.0 LANGUAGES C) +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version.txt version) + +project(zenohpico VERSION ${version} LANGUAGES C) + +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +include(helpers) + +# Configure header file to define the project version +set(ZENOH_PICO ${PROJECT_VERSION}) +set(ZENOH_PICO_MAJOR ${PROJECT_VERSION_MAJOR}) +set(ZENOH_PICO_MINOR ${PROJECT_VERSION_MINOR}) +set(ZENOH_PICO_PATCH ${PROJECT_VERSION_PATCH}) +set(ZENOH_PICO_TWEAK ${PROJECT_VERSION_TWEAK}) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico.h.in + ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico.h + @ONLY +) +set(project_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") +if(NOT DEFINED PROJECT_VERSION_TWEAK) + set(project_version "${project_version}") +elseif(PROJECT_VERSION_TWEAK EQUAL 0) + set(project_version "${project_version}-dev") +elseif(PROJECT_VERSION_TWEAK GREATER 1) + set(project_version "${project_version}-pre.${PROJECT_VERSION_TWEAK}") +endif() +status_print(project_version) + include(CMakePackageConfigHelpers) include(GNUInstallDirs) diff --git a/ci/scripts/build-linux.bash b/ci/scripts/build-linux.bash new file mode 100644 index 000000000..00b9f97df --- /dev/null +++ b/ci/scripts/build-linux.bash @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +set -xeo pipefail + +# Repository +readonly repo=${REPO:?input REPO is required} +# Release number +readonly version=${VERSION:?input TARGET is required} +# Build target +readonly target=${TARGET:?input TARGET is required} + +BUILD_TYPE=RELEASE make "$target" + +readonly out=$GITHUB_WORKSPACE +readonly repo_name=${repo#*/} +readonly archive_lib=$out/$repo_name-$version-$target.zip +readonly archive_deb=$out/$repo_name-$version-$target-deb-pkgs.zip +readonly archive_rpm=$out/$repo_name-$version-$target-rpm-pkgs.zip +readonly archive_examples=$out/$repo_name-$version-$target-examples.zip + +cd crossbuilds/"$target" +zip -r "$archive_lib" lib +cd - +zip -r "$archive_lib" include + +cd crossbuilds/"$target"/packages +zip "$archive_deb" ./*.deb +zip "$archive_rpm" ./*.rpm +cd - + +cd crossbuilds/"$target"/examples +zip "$archive_examples" ./* +cd - + +{ echo "archive-lib=$(basename "$archive_lib")"; + echo "archive-deb=$(basename "$archive_deb")"; + echo "archive-rpm=$(basename "$archive_rpm")"; + echo "archive-examples=$(basename "$archive_examples")"; +} >> "$GITHUB_OUTPUT" diff --git a/ci/scripts/build-macos.bash b/ci/scripts/build-macos.bash new file mode 100644 index 000000000..b04714283 --- /dev/null +++ b/ci/scripts/build-macos.bash @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +set -xeo pipefail + +# Repository +readonly repo=${REPO:?input REPO is required} +# Release number +readonly version=${VERSION:?input VERSION is required} + +BUILD_TYPE=RELEASE make + +readonly out=$GITHUB_WORKSPACE +readonly repo_name=${repo#*/} +readonly archive_lib=$out/$repo_name-$version-macos-x64.zip +readonly archive_examples=$out/$repo_name-$version-macos-x64-examples.zip + +cd build +zip -r "$archive_lib" lib +cd .. +zip -r "$archive_lib" include + +cd build/examples +zip "$archive_examples" ./* +cd .. + +{ echo "archive-lib=$(basename "$archive_lib")"; + echo "archive-examples=$(basename "$archive_examples")"; +} >> "$GITHUB_OUTPUT" diff --git a/ci/scripts/bump-and-tag.bash b/ci/scripts/bump-and-tag.bash new file mode 100644 index 000000000..58883d627 --- /dev/null +++ b/ci/scripts/bump-and-tag.bash @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -xeo pipefail + +# Release number +readonly version=${VERSION:-input VERSION is required} +# Git actor name +readonly git_user_name=${GIT_USER_NAME:?input GIT_USER_NAME is required} +# Git actor email +readonly git_user_email=${GIT_USER_EMAIL:?input GIT_USER_EMAIL is required} + +export GIT_AUTHOR_NAME=$git_user_name +export GIT_AUTHOR_EMAIL=$git_user_email +export GIT_COMMITTER_NAME=$git_user_name +export GIT_COMMITTER_EMAIL=$git_user_email + +# Bump CMake project version +printf '%s' "$version" > version.txt + +git commit version.txt -m "chore: Bump version to $version" +git tag --force "$version" -m "v$version" +git log -10 +git show-ref --tags +git push --force origin +git push --force origin "$version" diff --git a/ci/scripts/pre-build.bash b/ci/scripts/pre-build.bash new file mode 100644 index 000000000..c541076a5 --- /dev/null +++ b/ci/scripts/pre-build.bash @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -xeo pipefail + +# Extract cross-compilation targets from the Makefile +crossbuild_targets=$(sed -n 's/^CROSSBUILD_TARGETS=\(.*\)/\1/p' GNUmakefile | head -n1) +target_matrix="{\"target\": [\"${crossbuild_targets// /\",\"}\"]}" +echo "build-linux-matrix=$target_matrix" >> "$GITHUB_OUTPUT" diff --git a/docs/api.rst b/docs/api.rst index 7d75a8ac1..c51bb4e07 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -25,7 +25,6 @@ Enums .. autocenum:: constants.h::z_whatami_t .. autocenum:: constants.h::zp_keyexpr_canon_status_t .. autocenum:: constants.h::z_sample_kind_t -.. autocenum:: constants.h::z_encoding_id_t .. autocenum:: constants.h::z_consolidation_mode_t .. autocenum:: constants.h::z_reliability_t .. autocenum:: constants.h::z_reply_tag_t @@ -293,14 +292,14 @@ Primitives .. autocfunction:: primitives.h::z_scouting_config_from .. autocfunction:: primitives.h::zp_scouting_config_get .. autocfunction:: primitives.h::zp_scouting_config_insert -.. autocfunction:: primitives.h::zp_encoding_make -.. autocfunction:: primitives.h::zp_encoding_default .. autocfunction:: primitives.h::z_encoding_check .. autocfunction:: primitives.h::z_encoding_drop .. autocfunction:: primitives.h::z_encoding_loan .. autocfunction:: primitives.h::z_encoding_loan_mut .. autocfunction:: primitives.h::z_encoding_move .. autocfunction:: primitives.h::z_encoding_null +.. autocfunction:: primitives.h::z_encoding_from_str +.. autocfunction:: primitives.h::z_encoding_to_string .. autocfunction:: primitives.h::z_reply_err_payload .. autocfunction:: primitives.h::z_reply_err_encoding .. autocfunction:: primitives.h::z_slice_data diff --git a/docs/conf.py b/docs/conf.py index 37caaf948..adaff5535 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -21,7 +21,8 @@ project = 'zenoh-pico' copyright = '2017, 2022 ZettaScale Technology Inc' author = 'ZettaScale Zenoh team' -release = '0.11.0.0' +with open("../version.txt", "rt") as f: + release = f.read() # -- General configuration --------------------------------------------------- master_doc = 'index' diff --git a/examples/unix/c11/z_pub.c b/examples/unix/c11/z_pub.c index f65f7a172..958806740 100644 --- a/examples/unix/c11/z_pub.c +++ b/examples/unix/c11/z_pub.c @@ -116,14 +116,7 @@ int main(int argc, char **argv) { z_owned_bytes_t payload; z_bytes_serialize_from_string(&payload, buf); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, "utf8"); - z_publisher_put_options_t options; - z_publisher_put_options_default(&options); - options.encoding = z_move(encoding); - - z_publisher_put(z_loan(pub), z_move(payload), &options); + z_publisher_put(z_loan(pub), z_move(payload), NULL); } // Clean up z_undeclare_publisher(z_move(pub)); diff --git a/examples/unix/c11/z_pub_attachment.c b/examples/unix/c11/z_pub_attachment.c index 023c31dea..b9e793e2e 100644 --- a/examples/unix/c11/z_pub_attachment.c +++ b/examples/unix/c11/z_pub_attachment.c @@ -141,6 +141,9 @@ int main(int argc, char **argv) { // Allocate buffer char buf_ind[16]; + // Create encoding + z_owned_encoding_t encoding; + // Publish data printf("Press CTRL-C to quit...\n"); char buf[256]; @@ -160,6 +163,10 @@ int main(int argc, char **argv) { z_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&ctx); options.attachment = z_move(attachment); + // Add encoding value + z_encoding_from_str(&encoding, "text/plain;utf8"); + options.encoding = z_move(encoding); + z_publisher_put(z_loan(pub), z_move(payload), &options); } // Clean up diff --git a/examples/unix/c11/z_put.c b/examples/unix/c11/z_put.c index 90efbb848..26d8023a6 100644 --- a/examples/unix/c11/z_put.c +++ b/examples/unix/c11/z_put.c @@ -101,15 +101,8 @@ int main(int argc, char **argv) { z_owned_bytes_t payload; z_bytes_serialize_from_string(&payload, value); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - printf("Putting Data ('%s': '%s')...\n", keyexpr, value); - z_put_options_t options; - z_put_options_default(&options); - options.encoding = z_move(encoding); - if (z_put(z_loan(s), z_loan(ke), z_move(payload), &options) < 0) { + if (z_put(z_loan(s), z_loan(ke), z_move(payload), NULL) < 0) { printf("Oh no! Put has failed...\n"); } // Clean up diff --git a/examples/unix/c11/z_queryable.c b/examples/unix/c11/z_queryable.c index 394b6cd0e..84ac4e59f 100644 --- a/examples/unix/c11/z_queryable.c +++ b/examples/unix/c11/z_queryable.c @@ -39,19 +39,11 @@ void query_handler(const z_loaned_query_t *query, void *ctx) { } z_drop(z_move(payload_string)); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - - z_query_reply_options_t options; - z_query_reply_options_default(&options); - options.encoding = z_move(encoding); - // Reply value encoding z_owned_bytes_t reply_payload; z_bytes_serialize_from_string(&reply_payload, value); - z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), &options); + z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), NULL); z_drop(z_move(keystr)); msg_nb++; } diff --git a/examples/unix/c11/z_queryable_attachment.c b/examples/unix/c11/z_queryable_attachment.c index 807870ec4..dba0810e8 100644 --- a/examples/unix/c11/z_queryable_attachment.c +++ b/examples/unix/c11/z_queryable_attachment.c @@ -126,14 +126,6 @@ void query_handler(const z_loaned_query_t *query, void *ctx) { drop_attachment(&kvp); z_drop(z_move(payload_string)); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - - z_query_reply_options_t options; - z_query_reply_options_default(&options); - options.encoding = z_move(encoding); - // Reply value encoding z_owned_bytes_t reply_payload; z_bytes_serialize_from_string(&reply_payload, value); @@ -144,6 +136,9 @@ void query_handler(const z_loaned_query_t *query, void *ctx) { kv_pairs_tx_t kv_ctx = (kv_pairs_tx_t){.data = kvs, .current_idx = 0, .len = 1}; z_owned_bytes_t attachment; z_bytes_serialize_from_iter(&attachment, create_attachment_iter, (void *)&kv_ctx); + + z_query_reply_options_t options; + z_query_reply_options_default(&options); options.attachment = z_move(attachment); z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), &options); diff --git a/examples/unix/c11/z_sub_attachment.c b/examples/unix/c11/z_sub_attachment.c index c5dd40782..5038c2ae6 100644 --- a/examples/unix/c11/z_sub_attachment.c +++ b/examples/unix/c11/z_sub_attachment.c @@ -73,7 +73,11 @@ void data_handler(const z_loaned_sample_t *sample, void *ctx) { z_keyexpr_to_string(z_sample_keyexpr(sample), &keystr); z_owned_string_t value; z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + z_owned_string_t encoding; + z_encoding_to_string(z_sample_encoding(sample), &encoding); + printf(">> [Subscriber] Received ('%s': '%s')\n", z_string_data(z_loan(keystr)), z_string_data(z_loan(value))); + printf(" with encoding: %s\n", z_string_data(z_loan(encoding))); // Check attachment kv_pairs_t kvp = {.current_idx = 0, .len = KVP_LEN, .data = (kv_pair_t *)malloc(KVP_LEN * sizeof(kv_pair_t))}; parse_attachment(&kvp, z_sample_attachment(sample)); @@ -83,6 +87,7 @@ void data_handler(const z_loaned_sample_t *sample, void *ctx) { drop_attachment(&kvp); z_drop(z_move(keystr)); z_drop(z_move(value)); + z_drop(z_move(encoding)); msg_nb++; } diff --git a/examples/unix/c99/z_pub.c b/examples/unix/c99/z_pub.c index 5395865c3..840bb11c0 100644 --- a/examples/unix/c99/z_pub.c +++ b/examples/unix/c99/z_pub.c @@ -106,14 +106,7 @@ int main(int argc, char **argv) { z_owned_bytes_t payload; z_bytes_serialize_from_string(&payload, buf); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - z_publisher_put_options_t options; - z_publisher_put_options_default(&options); - options.encoding = z_encoding_move(&encoding); - - z_publisher_put(z_publisher_loan(&pub), z_bytes_move(&payload), &options); + z_publisher_put(z_publisher_loan(&pub), z_bytes_move(&payload), NULL); } // Clean up z_undeclare_publisher(z_publisher_move(&pub)); diff --git a/examples/unix/c99/z_put.c b/examples/unix/c99/z_put.c index dff0186e1..1a68f33b0 100644 --- a/examples/unix/c99/z_put.c +++ b/examples/unix/c99/z_put.c @@ -97,15 +97,8 @@ int main(int argc, char **argv) { z_owned_bytes_t payload; z_bytes_serialize_from_string(&payload, value); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - printf("Putting Data ('%s': '%s')...\n", keyexpr, value); - z_put_options_t options; - z_put_options_default(&options); - options.encoding = z_encoding_move(&encoding); - if (z_put(z_session_loan(&s), z_keyexpr_loan(&ke), z_bytes_move(&payload), &options) < 0) { + if (z_put(z_session_loan(&s), z_keyexpr_loan(&ke), z_bytes_move(&payload), NULL) < 0) { printf("Oh no! Put has failed...\n"); } diff --git a/examples/unix/c99/z_queryable.c b/examples/unix/c99/z_queryable.c index 22f1e4cd3..bc098b63e 100644 --- a/examples/unix/c99/z_queryable.c +++ b/examples/unix/c99/z_queryable.c @@ -38,18 +38,11 @@ void query_handler(const z_loaned_query_t *query, void *ctx) { } z_string_drop(z_string_move(&payload_string)); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - - z_query_reply_options_t options; - z_query_reply_options_default(&options); - options.encoding = z_encoding_move(&encoding); // Reply value encoding z_owned_bytes_t reply_payload; z_bytes_serialize_from_string(&reply_payload, value); - z_query_reply(query, z_query_keyexpr(query), z_bytes_move(&reply_payload), &options); + z_query_reply(query, z_query_keyexpr(query), z_bytes_move(&reply_payload), NULL); z_string_drop(z_string_move(&keystr)); } diff --git a/examples/windows/z_pub.c b/examples/windows/z_pub.c index 13e748a22..6b0c4bd28 100644 --- a/examples/windows/z_pub.c +++ b/examples/windows/z_pub.c @@ -68,14 +68,7 @@ int main(int argc, char **argv) { z_owned_bytes_t payload; z_bytes_serialize_from_string(&payload, buf); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - z_publisher_put_options_t options; - z_publisher_put_options_default(&options); - options.encoding = z_move(encoding); - - z_publisher_put(z_loan(pub), z_move(payload), &options); + z_publisher_put(z_loan(pub), z_move(payload), NULL); } // Clean-up diff --git a/examples/windows/z_put.c b/examples/windows/z_put.c index 4b3a76dda..3fa50939b 100644 --- a/examples/windows/z_put.c +++ b/examples/windows/z_put.c @@ -64,15 +64,8 @@ int main(int argc, char **argv) { z_owned_bytes_t payload; z_bytes_serialize_from_string(&payload, value); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - printf("Putting Data ('%s': '%s')...\n", keyexpr, value); - z_put_options_t options; - z_put_options_default(&options); - options.encoding = z_move(encoding); - if (z_put(z_loan(s), z_loan(ke), z_move(payload), &options) < 0) { + if (z_put(z_loan(s), z_loan(ke), z_move(payload), NULL) < 0) { printf("Oh no! Put has failed...\n"); } diff --git a/examples/windows/z_queryable.c b/examples/windows/z_queryable.c index 294afd37e..3415e2260 100644 --- a/examples/windows/z_queryable.c +++ b/examples/windows/z_queryable.c @@ -38,18 +38,11 @@ void query_handler(const z_loaned_query_t *query, void *ctx) { } z_drop(z_move(payload_string)); - // Create encoding - z_owned_encoding_t encoding; - zp_encoding_make(&encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - - z_query_reply_options_t options; - z_query_reply_options_default(&options); - options.encoding = z_move(encoding); // Reply value encoding z_owned_bytes_t reply_payload; z_bytes_serialize_from_string(&reply_payload, value); - z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), &options); + z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), NULL); z_drop(z_move(keystr)); } diff --git a/include/zenoh-pico.h b/include/zenoh-pico.h index 4f9ebb636..26569f564 100644 --- a/include/zenoh-pico.h +++ b/include/zenoh-pico.h @@ -12,12 +12,14 @@ // ZettaScale Zenoh Team, // +// ⚠️ This file is auto-generated from include/zenoh-pico.h.in + #ifndef ZENOH_PICO_H #define ZENOH_PICO_H -#define ZENOH_PICO "0.11.0.0" -#define ZENOH_PICO_MAJOR 0 -#define ZENOH_PICO_MINOR 11 +#define ZENOH_PICO "1.0.0.0" +#define ZENOH_PICO_MAJOR 1 +#define ZENOH_PICO_MINOR 0 #define ZENOH_PICO_PATCH 0 #define ZENOH_PICO_TWEAK 0 diff --git a/include/zenoh-pico.h.in b/include/zenoh-pico.h.in new file mode 100644 index 000000000..86e4ffc57 --- /dev/null +++ b/include/zenoh-pico.h.in @@ -0,0 +1,32 @@ +// +// Copyright (c) 2022 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +// ⚠️ This file is auto-generated from include/zenoh-pico.h.in + +#ifndef ZENOH_PICO_H +#define ZENOH_PICO_H + +#define ZENOH_PICO "@ZENOH_PICO@" +#define ZENOH_PICO_MAJOR @ZENOH_PICO_MAJOR@ +#define ZENOH_PICO_MINOR @ZENOH_PICO_MINOR@ +#define ZENOH_PICO_PATCH @ZENOH_PICO_PATCH@ +#define ZENOH_PICO_TWEAK @ZENOH_PICO_TWEAK@ + +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/api/handlers.h" +#include "zenoh-pico/api/macros.h" +#include "zenoh-pico/api/primitives.h" +#include "zenoh-pico/api/types.h" + +#endif /* ZENOH_PICO_H */ diff --git a/include/zenoh-pico/api/constants.h b/include/zenoh-pico/api/constants.h index 58fecb460..579da9cda 100644 --- a/include/zenoh-pico/api/constants.h +++ b/include/zenoh-pico/api/constants.h @@ -96,69 +96,81 @@ typedef enum { Z_SAMPLE_KIND_PUT = 0, Z_SAMPLE_KIND_DELETE = 1 } z_sample_kind_t * different operations depending on the encoding value. * * A set of associated constants are provided to cover the most common encodings for user convenience. - * This is particularly useful in helping Zenoh to perform additional network optimizations. + * This is particularly useful in helping Zenoh to perform additional wire-level optimizations. + * + * Register your encoding metadata from a string with :c:func:`z_encoding_from_str`. To get the optimization, you need + * Z_FEATURE_ENCODING_VALUES to 1 and your string should follow the format: ";" + * + * E.g: "text/plain;utf8" + * + * Here is the list of constants: */ -typedef enum { - Z_ENCODING_ID_BYTES = 0, // Primitives types supported in all Zenoh bindings, just some bytes. - Z_ENCODING_ID_INT = 1, // A VLE-encoded signed little-endian integer. - Z_ENCODING_ID_UINT = 2, // A VLE-encoded little-endian unsigned integer. - Z_ENCODING_ID_FLOAT = 3, // A VLE-encoded float. - Z_ENCODING_ID_BOOL = 4, // A boolean. - Z_ENCODING_ID_STRING = 5, // A UTF-8 string. - Z_ENCODING_ID_ERROR = 6, // A zenoh error. - Z_ENCODING_ID_APP_OCTET_STREAM = 7, // An application-specific stream of bytes. - Z_ENCODING_ID_TEXT_PLAIN = 8, // A textual file. - Z_ENCODING_ID_APP_JSON = 9, // JSON data intended to be consumed by an application. - Z_ENCODING_ID_TEXT_JSON = 10, // JSON data intended to be human readable. - Z_ENCODING_ID_APP_CDR = 11, // A Common Data Representation (CDR)-encoded data. - Z_ENCODING_ID_APP_CBOR = 12, // A Concise Binary Object Representation (CBOR)-encoded data. - Z_ENCODING_ID_APP_YAML = 13, // YAML data intended to be consumed by an application. - Z_ENCODING_ID_TEXT_YAML = 14, // YAML data intended to be human readable. - Z_ENCODING_ID_TEXT_JSON5 = 15, // JSON5 encoded data that are human readable. - Z_ENCODING_ID_APP_PYTHON_SERIALIZED_OBJECT = 16, // A Python object serialized using pickle. - Z_ENCODING_ID_APP_PROTOBUF = 17, // An application-specific protobuf-encoded data. - Z_ENCODING_ID_APP_JAVA_SERIALIZED_OBJECT = 18, // A Java serialized object. - Z_ENCODING_ID_APP_OPENMETRICS_TEXT = 19, // An openmetrics data. - Z_ENCODING_ID_IMAGE_PNG = 20, // A Portable Network Graphics (PNG) image. - Z_ENCODING_ID_IMAGE_JPEG = 21, // A Joint Photographic Experts Group (JPEG) image. - Z_ENCODING_ID_IMAGE_GIF = 22, // A Graphics Interchange Format (GIF) image. - Z_ENCODING_ID_IMAGE_BMP = 23, // A BitMap (BMP) image. - Z_ENCODING_ID_IMAGE_WEBP = 24, // A Web Portable (WebP) image. - Z_ENCODING_ID_APP_XML = 25, // An XML file intended to be consumed by an application. - Z_ENCODING_ID_APP_X_WWW_FORM_URLENCODED = 26, // An encoded a list of tuples. - Z_ENCODING_ID_TEXT_HTML = 27, // An HTML file. - Z_ENCODING_ID_TEXT_XML = 28, // An XML file that is human readable. - Z_ENCODING_ID_TEXT_CSS = 29, // A CSS file. - Z_ENCODING_ID_TEXT_JAVASCRIPT = 30, // A JavaScript file. - Z_ENCODING_ID_TEXT_MARKDOWN = 31, // A MarkDown file. - Z_ENCODING_ID_TEXT_CSV = 32, // A CSV file. - Z_ENCODING_ID_APP_SQL = 33, // An application-specific SQL query. - Z_ENCODING_ID_APP_COAP_PAYLOAD = 34, // Constrained Application Protocol (CoAP) data. - Z_ENCODING_ID_APP_JSON_PATCH_JSON = 35, // Defines a JSON document structure. - Z_ENCODING_ID_APP_JSON_SEQ = 36, // A JSON text sequence. - Z_ENCODING_ID_APP_JSONPATH = 37, // A JSONPath defines a string syntax. - Z_ENCODING_ID_APP_JWT = 38, // A JSON Web Token (JWT). - Z_ENCODING_ID_APP_MP4 = 39, // An application-specific MPEG-4 encoded data. - Z_ENCODING_ID_APP_SOAP_XML = 40, // A SOAP 1.2 message serialized as XML 1.0. - Z_ENCODING_ID_APP_YANG = 41, // A YANG-encoded data. - Z_ENCODING_ID_AUDIO_AAC = 42, // A MPEG-4 Advanced Audio Coding (AAC) media. - Z_ENCODING_ID_AUDIO_FLAC = 43, // A Free Lossless Audio Codec (FLAC) media. - Z_ENCODING_ID_AUDIO_MP4 = 44, // An audio codec defined in MPEG-4. - Z_ENCODING_ID_AUDIO_OGG = 45, // An Ogg-encapsulated audio stream. - Z_ENCODING_ID_AUDIO_VORBIS = 46, // A Vorbis-encoded audio stream. - Z_ENCODING_ID_VIDEO_H261 = 47, // A h261-encoded video stream. - Z_ENCODING_ID_VIDEO_H263 = 48, // A h263-encoded video stream. - Z_ENCODING_ID_VIDEO_H264 = 49, // A h264-encoded video stream. - Z_ENCODING_ID_VIDEO_H265 = 50, // A h265-encoded video stream. - Z_ENCODING_ID_VIDEO_H266 = 51, // A h266-encoded video stream. - Z_ENCODING_ID_VIDEO_MP4 = 52, // A video codec defined in MPEG-4. - Z_ENCODING_ID_VIDEO_OGG = 53, // An Ogg-encapsulated video stream. - Z_ENCODING_ID_VIDEO_RAW = 54, // An uncompressed, studio-quality video stream. - Z_ENCODING_ID_VIDEO_VP8 = 55, // A VP8-encoded video stream. - Z_ENCODING_ID_VIDEO_VP9 = 56 // A VP9-encoded video stream. -} z_encoding_id_t; - -#define Z_ENCODING_ID_DEFAULT Z_ENCODING_ID_BYTES +// "zenoh/bytes" +// "zenoh/int8" +// "zenoh/int16" +// "zenoh/int32" +// "zenoh/int64" +// "zenoh/int128" +// "zenoh/uint8" +// "zenoh/uint16" +// "zenoh/uint32" +// "zenoh/uint64" +// "zenoh/uint128" +// "zenoh/float32" +// "zenoh/float64" +// "zenoh/bool" +// "zenoh/string" +// "zenoh/error" +// "application/octet-stream" +// "text/plain" +// "application/json" +// "text/json" +// "application/cdr" +// "application/cbor" +// "application/yaml" +// "text/yaml" +// "text/json5" +// "application/python-serialized-object" +// "application/protobuf" +// "application/java-serialized-object" +// "application/openmetrics-text" +// "image/png" +// "image/jpeg" +// "image/gif" +// "image/bmp" +// "image/webp" +// "application/xml" +// "application/x-www-form-urlencoded" +// "text/html" +// "text/xml" +// "text/css" +// "text/javascript" +// "text/markdown" +// "text/csv" +// "application/sql" +// "application/coap-payload" +// "application/json-patch+json" +// "application/json-seq" +// "application/jsonpath" +// "application/jwt" +// "application/mp4" +// "application/soap+xml" +// "application/yang" +// "audio/aac" +// "audio/flac" +// "audio/mp4" +// "audio/ogg" +// "audio/vorbis" +// "video/h261" +// "video/h263" +// "video/h264" +// "video/h265" +// "video/h266" +// "video/mp4" +// "video/ogg" +// "video/raw" +// "video/vp8" +// "video/vp9" /** * Consolidation mode values. diff --git a/include/zenoh-pico/api/macros.h b/include/zenoh-pico/api/macros.h index aad0dd4e9..a17d40c41 100644 --- a/include/zenoh-pico/api/macros.h +++ b/include/zenoh-pico/api/macros.h @@ -14,6 +14,7 @@ #ifndef ZENOH_PICO_API_MACROS_H #define ZENOH_PICO_API_MACROS_H +#include "zenoh-pico/api/handlers.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index dfbd7ba55..c5f680025 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -338,30 +338,6 @@ const char *zp_scouting_config_get(const z_loaned_scouting_config_t *config, uin */ int8_t zp_scouting_config_insert(z_loaned_scouting_config_t *config, uint8_t key, const char *value); -/** - * Builds a new :c:type:`z_owned_encoding_t`. - * - * Parameters: - * encoding: Pointer to an uninitialized :c:type:`z_owned_encoding_t`. - * id: A known :c:type:`z_encoding_id_t` value. - * schema: Pointer to a custom schema string value. - * - * Return: - * ``0`` if creation successful, ``negative value`` otherwise. - */ -int8_t zp_encoding_make(z_owned_encoding_t *encoding, z_encoding_id_t id, const char *schema); - -/** - * Builds a new a :c:type:`z_owned_encoding_t` with default value. - * - * Parameters: - * encoding: Pointer to an uninitialized :c:type:`z_owned_encoding_t`. - * - * Return: - * ``0`` if creation successful, ``negative value`` otherwise. - */ -int8_t zp_encoding_default(z_owned_encoding_t *encoding); - /** * Checks if a :c:type:`z_owned_encoding_t` has non-default values. * @@ -411,15 +387,36 @@ z_loaned_encoding_t *z_encoding_loan_mut(z_owned_encoding_t *encoding); z_owned_encoding_t *z_encoding_move(z_owned_encoding_t *encoding); /** - * Builds a :c:type:`z_owned_encoding_t` with default value. + * Initialize a :c:type:`z_owned_encoding_t` with default value. + * + * Parameters: + * encoding: Pointer to an uninitialized :c:type:`z_owned_encoding_t`. + */ +void z_encoding_null(z_owned_encoding_t *encoding); + +/** + * Builds a :c:type:`z_owned_encoding_t` from a null terminated string. * * Parameters: * encoding: Pointer to an uninitialized :c:type:`z_owned_encoding_t`. + * s: Pointer to the null terminated string to use. + * + * Return: + * ``0`` if creation successful,``negative value`` otherwise. + */ +int8_t z_encoding_from_str(z_owned_encoding_t *encoding, const char *s); + +/** + * Builds a string from a :c:type:`z_loaned_encoding_t`. + * + * Parameters: + * encoding: Pointer to the :c:type:`z_loaned_encoding_t` to use. + * string: Pointer to an uninitialized :c:type:`z_owned_string_t` to store the string. * * Return: * ``0`` if creation successful,``negative value`` otherwise. */ -int8_t z_encoding_null(z_owned_encoding_t *encoding); +int8_t z_encoding_to_string(const z_loaned_encoding_t *encoding, z_owned_string_t *string); /** * Gets the bytes data from a reply error payload by aliasing it. diff --git a/include/zenoh-pico/api/types.h b/include/zenoh-pico/api/types.h index 4cfb71e14..305dacbc7 100644 --- a/include/zenoh-pico/api/types.h +++ b/include/zenoh-pico/api/types.h @@ -194,7 +194,7 @@ _Z_LOANED_TYPE(_z_query_rc_t, query) * Represents the encoding of a payload, in a MIME-like format. * * Members: - * z_encoding_id_t prefix: The integer prefix of this encoding. + * uint16_t prefix: The integer prefix of this encoding. * z_loaned_slice_t* suffix: The suffix of this encoding. It MUST be a valid UTF-8 string. */ _Z_OWNED_TYPE_PTR(_z_encoding_t, encoding) diff --git a/include/zenoh-pico/collections/string.h b/include/zenoh-pico/collections/string.h index 24546d00f..a37ffa110 100644 --- a/include/zenoh-pico/collections/string.h +++ b/include/zenoh-pico/collections/string.h @@ -70,6 +70,7 @@ typedef struct { } _z_string_t; _z_string_t _z_string_null(void); +_Bool _z_string_check(_z_string_t value); _z_string_t _z_string_make(const char *value); _z_string_t _z_string_wrap(char *value); _z_string_t *_z_string_make_as_ptr(const char *value); diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index d7137b3b2..71613d41b 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -239,6 +239,13 @@ #define Z_FEATURE_INTEREST 0 #endif +/** + * Enable encoding values. + */ +#ifndef Z_FEATURE_ENCODING_VALUES +#define Z_FEATURE_ENCODING_VALUES 1 +#endif + /*------------------ Compile-time configuration properties ------------------*/ /** * Default length for Zenoh ID. Maximum size is 16 bytes. diff --git a/include/zenoh-pico/net/encoding.h b/include/zenoh-pico/net/encoding.h index cb17a1622..25e6c6260 100644 --- a/include/zenoh-pico/net/encoding.h +++ b/include/zenoh-pico/net/encoding.h @@ -15,18 +15,20 @@ #define ZENOH_PICO_ENCODING_NETAPI_H #include "zenoh-pico/api/constants.h" -#include "zenoh-pico/collections/slice.h" +#include "zenoh-pico/collections/string.h" + +#define _Z_ENCODING_ID_DEFAULT 0 /** * A zenoh encoding. */ typedef struct _z_encoding_t { - _z_slice_t schema; + _z_string_t schema; uint16_t id; } _z_encoding_t; -int8_t _z_encoding_make(_z_encoding_t *encoding, z_encoding_id_t id, const char *schema); -_z_encoding_t _z_encoding_wrap(z_encoding_id_t id, const char *schema); +int8_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema); +_z_encoding_t _z_encoding_wrap(uint16_t id, const char *schema); _z_encoding_t _z_encoding_null(void); void _z_encoding_clear(_z_encoding_t *encoding); _Bool _z_encoding_check(const _z_encoding_t *encoding); diff --git a/include/zenoh-pico/protocol/codec/core.h b/include/zenoh-pico/protocol/codec/core.h index 706e7d9ab..e4354aade 100644 --- a/include/zenoh-pico/protocol/codec/core.h +++ b/include/zenoh-pico/protocol/codec/core.h @@ -57,15 +57,15 @@ int8_t _z_slice_val_decode(_z_slice_t *bs, _z_zbuf_t *buf); int8_t _z_slice_val_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf); int8_t _z_slice_encode(_z_wbuf_t *buf, const _z_slice_t *bs); -size_t _z_slice_encode_len(const _z_slice_t *bs); int8_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *buf); int8_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf); int8_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs); int8_t _z_zbuf_read_exact(_z_zbuf_t *zbf, uint8_t *dest, size_t length); int8_t _z_str_encode(_z_wbuf_t *buf, const char *s); -int8_t _z_zstr_encode(_z_wbuf_t *wbf, const _z_string_t *s); int8_t _z_str_decode(char **str, _z_zbuf_t *buf); +int8_t _z_string_encode(_z_wbuf_t *wbf, const _z_string_t *s); +int8_t _z_string_decode(_z_string_t *str, _z_zbuf_t *zbf); size_t _z_encoding_len(const _z_encoding_t *en); int8_t _z_encoding_encode(_z_wbuf_t *wbf, const _z_encoding_t *en); diff --git a/src/api/api.c b/src/api/api.c index 4ad100328..bd7ca283c 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -18,6 +18,7 @@ #include #include +#include "zenoh-pico/api/constants.h" #include "zenoh-pico/api/olv_macros.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" @@ -221,18 +222,151 @@ int8_t zp_scouting_config_insert(z_loaned_scouting_config_t *sc, uint8_t key, co return _zp_config_insert(sc, key, value); } -int8_t zp_encoding_make(z_owned_encoding_t *encoding, z_encoding_id_t id, const char *schema) { - // Init encoding - encoding->_val = (_z_encoding_t *)z_malloc(sizeof(_z_encoding_t)); - if (encoding->_val == NULL) { +#if Z_FEATURE_ENCODING_VALUES == 1 +#define ENCODING_SCHEMA_SEPARATOR ';' + +const char *ENCODING_VALUES_ID_TO_STR[] = { + "zenoh/bytes", + "zenoh/int8", + "zenoh/int16", + "zenoh/int32", + "zenoh/int64", + "zenoh/int128", + "zenoh/uint8", + "zenoh/uint16", + "zenoh/uint32", + "zenoh/uint64", + "zenoh/uint128", + "zenoh/float32", + "zenoh/float64", + "zenoh/bool", + "zenoh/string", + "zenoh/error", + "application/octet-stream", + "text/plain", + "application/json", + "text/json", + "application/cdr", + "application/cbor", + "application/yaml", + "text/yaml", + "text/json5", + "application/python-serialized-object", + "application/protobuf", + "application/java-serialized-object", + "application/openmetrics-text", + "image/png", + "image/jpeg", + "image/gif", + "image/bmp", + "image/webp", + "application/xml", + "application/x-www-form-urlencoded", + "text/html", + "text/xml", + "text/css", + "text/javascript", + "text/markdown", + "text/csv", + "application/sql", + "application/coap-payload", + "application/json-patch+json", + "application/json-seq", + "application/jsonpath", + "application/jwt", + "application/mp4", + "application/soap+xml", + "application/yang", + "audio/aac", + "audio/flac", + "audio/mp4", + "audio/ogg", + "audio/vorbis", + "video/h261", + "video/h263", + "video/h264", + "video/h265", + "video/h266", + "video/mp4", + "video/ogg", + "video/raw", + "video/vp8", + "video/vp9", +}; + +static uint16_t _z_encoding_values_str_to_int(const char *schema, size_t len) { + for (size_t i = 0; i < _ZP_ARRAY_SIZE(ENCODING_VALUES_ID_TO_STR); i++) { + if (strncmp(schema, ENCODING_VALUES_ID_TO_STR[i], len) == 0) { + return (uint16_t)i; + } + } + return UINT16_MAX; +} + +static int8_t _z_encoding_convert_from_string(z_owned_encoding_t *encoding, const char *s) { + const char *id_end = strchr(s, ENCODING_SCHEMA_SEPARATOR); + // Check id_end value + corner cases + if ((id_end != NULL) && (id_end != s)) { + // Calc length of the segment before separator + size_t len = (size_t)(id_end - 1 - s); + uint16_t id = _z_encoding_values_str_to_int(s, len); + // Check id + if (id != UINT16_MAX) { + return _z_encoding_make(encoding->_val, id, (id_end[1] == '\0') ? NULL : ++id_end); + } + } + // By default store the string as schema + return _z_encoding_make(encoding->_val, _Z_ENCODING_ID_DEFAULT, s); +} + +static int8_t _z_encoding_convert_into_string(const z_loaned_encoding_t *encoding, z_owned_string_t *s) { + const char *prefix = NULL; + size_t prefix_len = 0; + // Convert id + if (encoding->id < _ZP_ARRAY_SIZE(ENCODING_VALUES_ID_TO_STR)) { + prefix = ENCODING_VALUES_ID_TO_STR[encoding->id]; + prefix_len = strlen(prefix); + } + _Bool has_schema = encoding->schema.len > 0; + // Size include null terminator + size_t total_len = prefix_len + encoding->schema.len + 1; + // Check for schema separator + if (has_schema) { + total_len += 1; + } + // Allocate string + char *value = (char *)z_malloc(sizeof(char) * total_len); + if (value == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - return _z_encoding_make(encoding->_val, id, schema); + // Copy prefix + char sep = ENCODING_SCHEMA_SEPARATOR; + (void)strncpy(value, prefix, prefix_len); + // Copy schema and separator + if (has_schema) { + (void)strncat(value, &sep, 1); + (void)strncat(value, encoding->schema.val, encoding->schema.len); + } + // Fill container + *s->_val = _z_string_wrap(value); + return _Z_RES_OK; +} + +#else +static int8_t _z_encoding_convert_from_string(z_owned_encoding_t *encoding, const char *s) { + return _z_encoding_make(encoding->_val, _Z_ENCODING_ID_DEFAULT, s); +} + +static int8_t _z_encoding_convert_into_string(const z_loaned_encoding_t *encoding, z_owned_string_t *s) { + _z_string_copy(s->_val, &encoding->schema); + return _Z_RES_OK; } +#endif + z_owned_encoding_t *z_encoding_move(z_owned_encoding_t *encoding) { return encoding; } -int8_t z_encoding_null(z_owned_encoding_t *encoding) { return zp_encoding_make(encoding, Z_ENCODING_ID_DEFAULT, NULL); } +void z_encoding_null(z_owned_encoding_t *encoding) { encoding->_val = NULL; } _Bool z_encoding_check(const z_owned_encoding_t *encoding) { return _z_encoding_check(encoding->_val); } @@ -240,8 +374,8 @@ void z_encoding_drop(z_owned_encoding_t *encoding) { if (encoding == NULL) { return; } - if (!_z_slice_is_empty(&encoding->_val->schema)) { - _z_slice_clear(&encoding->_val->schema); + if (_z_string_check(encoding->_val->schema)) { + _z_string_clear(&encoding->_val->schema); } z_free(encoding->_val); } @@ -259,6 +393,33 @@ const z_loaned_encoding_t *z_encoding_loan(const z_owned_encoding_t *encoding) { z_loaned_encoding_t *z_encoding_loan_mut(z_owned_encoding_t *encoding) { return encoding->_val; } +int8_t z_encoding_from_str(z_owned_encoding_t *encoding, const char *s) { + // Init owned encoding + z_encoding_null(encoding); + encoding->_val = (_z_encoding_t *)z_malloc(sizeof(_z_encoding_t)); + if (encoding->_val == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Convert string to encoding + if (s != NULL) { + return _z_encoding_convert_from_string(encoding, s); + } + return _Z_RES_OK; +} + +int8_t z_encoding_to_string(const z_loaned_encoding_t *encoding, z_owned_string_t *s) { + // Init owned string + z_string_null(s); + // Allocate owned string + s->_val = (_z_string_t *)z_malloc(sizeof(_z_string_t)); + if (s->_val == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Convert encoding to string + _z_encoding_convert_into_string(encoding, s); + return _Z_RES_OK; +} + const uint8_t *z_slice_data(const z_loaned_slice_t *slice) { return slice->start; } size_t z_slice_len(const z_loaned_slice_t *slice) { return slice->len; } diff --git a/src/collections/string.c b/src/collections/string.c index 52352b3d3..3d2ff0069 100644 --- a/src/collections/string.c +++ b/src/collections/string.c @@ -23,6 +23,8 @@ _z_string_t _z_string_null(void) { return s; } +_Bool _z_string_check(_z_string_t value) { return value.val != NULL; } + _z_string_t _z_string_make(const char *value) { _z_string_t s; s.val = _z_str_clone(value); diff --git a/src/link/endpoint.c b/src/link/endpoint.c index b2464ba10..d3274fd97 100644 --- a/src/link/endpoint.c +++ b/src/link/endpoint.c @@ -450,6 +450,6 @@ char *_z_endpoint_to_str(const _z_endpoint_t *endpoint) { } } // Clean up - _z_string_clear(locator); + _z_string_free(&locator); return ret; } diff --git a/src/net/encoding.c b/src/net/encoding.c index 406d10437..45d0b9e75 100644 --- a/src/net/encoding.c +++ b/src/net/encoding.c @@ -19,41 +19,39 @@ #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/result.h" -int8_t _z_encoding_make(_z_encoding_t *encoding, z_encoding_id_t id, const char *schema) { +int8_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema) { encoding->id = id; // Clone schema if (schema != NULL) { - encoding->schema = _z_slice_make(strlen(schema) + 1); - if (encoding->schema.start == NULL) { + encoding->schema = _z_string_make(schema); + if (encoding->schema.val == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - strcpy((char *)encoding->schema.start, schema); } else { - encoding->schema = _z_slice_empty(); + encoding->schema = _z_string_null(); } return _Z_RES_OK; } -_z_encoding_t _z_encoding_wrap(z_encoding_id_t id, const char *schema) { - return (_z_encoding_t){ - .id = id, .schema = _z_slice_wrap((const uint8_t *)schema, (schema == NULL) ? (size_t)0 : strlen(schema))}; +_z_encoding_t _z_encoding_wrap(uint16_t id, const char *schema) { + return (_z_encoding_t){.id = id, .schema = (schema == NULL) ? _z_string_null() : _z_string_wrap((char *)schema)}; } -_z_encoding_t _z_encoding_null(void) { return _z_encoding_wrap(Z_ENCODING_ID_DEFAULT, NULL); } +_z_encoding_t _z_encoding_null(void) { return _z_encoding_wrap(_Z_ENCODING_ID_DEFAULT, NULL); } -void _z_encoding_clear(_z_encoding_t *encoding) { _z_slice_clear(&encoding->schema); } +void _z_encoding_clear(_z_encoding_t *encoding) { _z_string_clear(&encoding->schema); } _Bool _z_encoding_check(const _z_encoding_t *encoding) { - return ((encoding->id != Z_ENCODING_ID_DEFAULT) || _z_slice_check(encoding->schema)); + return ((encoding->id != _Z_ENCODING_ID_DEFAULT) || _z_string_check(encoding->schema)); } void _z_encoding_copy(_z_encoding_t *dst, const _z_encoding_t *src) { dst->id = src->id; - _z_slice_copy(&dst->schema, &src->schema); + _z_string_copy(&dst->schema, &src->schema); } void _z_encoding_move(_z_encoding_t *dst, _z_encoding_t *src) { dst->id = src->id; - src->id = Z_ENCODING_ID_DEFAULT; - _z_slice_move(&dst->schema, &src->schema); + src->id = _Z_ENCODING_ID_DEFAULT; + _z_string_move(&dst->schema, &src->schema); } diff --git a/src/protocol/codec.c b/src/protocol/codec.c index cac24c15f..ab4211713 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -246,7 +246,6 @@ int8_t _z_slice_encode(_z_wbuf_t *wbf, const _z_slice_t *bs) { return ret; } -size_t _z_slice_encode_len(const _z_slice_t *bs) { return _z_zint_len(bs->len) + bs->len; } int8_t _z_slice_val_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; @@ -311,13 +310,6 @@ int8_t _z_str_encode(_z_wbuf_t *wbf, const char *s) { return _z_wbuf_write_bytes(wbf, (const uint8_t *)s, 0, len); } -int8_t _z_zstr_encode(_z_wbuf_t *wbf, const _z_string_t *s) { - size_t len = s->len - (size_t)1; - _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, len)) - // Note that this does not put the string terminator on the wire. - return _z_wbuf_write_bytes(wbf, (const uint8_t *)s->val, 0, len); -} - int8_t _z_str_decode(char **str, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; @@ -342,30 +334,58 @@ int8_t _z_str_decode(char **str, _z_zbuf_t *zbf) { *str = NULL; ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - return ret; } +int8_t _z_string_encode(_z_wbuf_t *wbf, const _z_string_t *s) { + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, s->len)) + // Note that this does not put the string terminator on the wire. + return _z_wbuf_write_bytes(wbf, (const uint8_t *)s->val, 0, s->len); +} + +int8_t _z_string_decode(_z_string_t *str, _z_zbuf_t *zbf) { + *str = _z_string_null(); + _z_zint_t len = 0; + // Decode string length + _Z_RETURN_IF_ERR(_z_zsize_decode(&len, zbf)); + // Check if we have enough bytes to read + if (_z_zbuf_len(zbf) < len) { + _Z_DEBUG("WARNING: Not enough bytes to read"); + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + // Allocate space for the string terminator + str->val = (char *)z_malloc(len + (size_t)1); + if (str->val == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + str->len = len; + // Add null terminator + str->val[len] = '\0'; + // Read bytes + _z_zbuf_read_bytes(zbf, (uint8_t *)str->val, 0, len); + return _Z_RES_OK; +} + /*------------------ encoding ------------------*/ #define _Z_ENCODING_FLAG_S 0x01 size_t _z_encoding_len(const _z_encoding_t *en) { size_t en_len = _z_zint_len((uint32_t)(en->id) << 1); - if (_z_slice_check(en->schema)) { - en_len += _z_slice_encode_len(&en->schema); + if (_z_string_check(en->schema)) { + en_len += _z_zint_len(en->schema.len) + en->schema.len; } return en_len; } int8_t _z_encoding_encode(_z_wbuf_t *wbf, const _z_encoding_t *en) { - _Bool has_schema = _z_slice_check(en->schema); + _Bool has_schema = _z_string_check(en->schema); uint32_t id = (uint32_t)(en->id) << 1; if (has_schema) { id |= _Z_ENCODING_FLAG_S; } _Z_RETURN_IF_ERR(_z_zint32_encode(wbf, id)); if (has_schema) { - _Z_RETURN_IF_ERR(_z_slice_encode(wbf, &en->schema)); + _Z_RETURN_IF_ERR(_z_string_encode(wbf, &en->schema)); } return _Z_RES_OK; } @@ -379,7 +399,7 @@ int8_t _z_encoding_decode(_z_encoding_t *en, _z_zbuf_t *zbf) { } en->id = (uint16_t)(id >> 1); if (has_schema) { - _Z_RETURN_IF_ERR(_z_slice_decode(&en->schema, zbf)); + _Z_RETURN_IF_ERR(_z_string_decode(&en->schema, zbf)); } return _Z_RES_OK; } diff --git a/src/protocol/codec/message.c b/src/protocol/codec/message.c index 608f9ba0f..f6cbadfa7 100644 --- a/src/protocol/codec/message.c +++ b/src/protocol/codec/message.c @@ -151,8 +151,8 @@ int8_t _z_locators_encode(_z_wbuf_t *wbf, const _z_locator_array_t *la) { _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, la->_len)) for (size_t i = 0; i < la->_len; i++) { _z_string_t *s = _z_locator_to_string(&la->_val[i]); - _Z_RETURN_IF_ERR(_z_zstr_encode(wbf, s)) - z_free(s); + _Z_RETURN_IF_ERR(_z_string_encode(wbf, s)) + _z_string_free(&s); } return ret; diff --git a/tests/attachment.py b/tests/attachment.py index b4f477541..8624939ce 100644 --- a/tests/attachment.py +++ b/tests/attachment.py @@ -30,22 +30,27 @@ def pub_and_sub(): Declaring Subscriber on 'demo/example/**'... Press CTRL-C to quit... >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 0] Pub from Pico!') + with encoding: text/plain;utf8 with attachment: 0: source, C 1: index, 0 >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 1] Pub from Pico!') + with encoding: text/plain;utf8 with attachment: 0: source, C 1: index, 1 >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 2] Pub from Pico!') + with encoding: text/plain;utf8 with attachment: 0: source, C 1: index, 2 >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 3] Pub from Pico!') + with encoding: text/plain;utf8 with attachment: 0: source, C 1: index, 3 >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 4] Pub from Pico!') + with encoding: text/plain;utf8 with attachment: 0: source, C 1: index, 4''' diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index be7bc2c36..21c9087d7 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -77,9 +77,7 @@ void query_handler(const z_loaned_query_t *query, void *arg) { z_query_parameters(query, &pred); (void)(pred); const z_loaned_bytes_t *payload = z_query_payload(query); - const z_loaned_encoding_t *encoding = z_query_encoding(query); (void)(payload); - (void)(encoding); z_query_reply_options_t _ret_qreply_opt; z_query_reply_options_default(&_ret_qreply_opt); @@ -319,9 +317,6 @@ int main(int argc, char **argv) { z_put_options_t _ret_put_opt; z_put_options_default(&_ret_put_opt); _ret_put_opt.congestion_control = Z_CONGESTION_CONTROL_BLOCK; - z_owned_encoding_t _ret_encoding; - zp_encoding_make(&_ret_encoding, Z_ENCODING_ID_TEXT_PLAIN, NULL); - _ret_put_opt.encoding = z_move(_ret_encoding); // Create payload z_owned_bytes_t payload; diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index d6720e7fe..fef9c7998 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -233,6 +233,8 @@ _z_string_vec_t gen_str_array(size_t size) { return sa; } +_z_string_t gen_string(size_t len) { return _z_string_wrap(gen_str(len)); } + _z_locator_array_t gen_locator_array(size_t size) { _z_locator_array_t la = _z_locator_array_make(size); for (size_t i = 0; i < size; i++) { @@ -249,9 +251,9 @@ _z_encoding_t gen_encoding(void) { _z_encoding_t en; en.id = gen_uint16(); if (gen_bool()) { - en.schema = gen_slice(16); + en.schema = gen_string(16); } else { - en.schema = _z_slice_empty(); + en.schema = _z_string_null(); } return en; } @@ -342,8 +344,8 @@ void assert_eq_locator_array(const _z_locator_array_t *left, const _z_locator_ar printf("%s:%s", ls->val, rs->val); if (i < left->_len - 1) printf(" "); - z_free(ls); - z_free(rs); + _z_string_free(&ls); + _z_string_free(&rs); assert(_z_locator_eq(l, r) == true); } @@ -507,6 +509,13 @@ void zbuf_extension(void) { /*------------------ Payload field ------------------*/ void assert_eq_slice(const _z_slice_t *left, const _z_slice_t *right) { assert_eq_uint8_array(left, right); } +void assert_eq_string(const _z_string_t *left, const _z_string_t *right) { + assert(left->len == right->len); + if (left->len > 0) { + assert(_z_str_eq(left->val, right->val) == true); + } +} + void assert_eq_bytes(const _z_bytes_t *left, const _z_bytes_t *right) { size_t len_left = _z_bytes_len(left); size_t len_right = _z_bytes_len(right); @@ -571,7 +580,7 @@ void assert_eq_source_info(const _z_source_info_t *left, const _z_source_info_t } void assert_eq_encoding(const _z_encoding_t *left, const _z_encoding_t *right) { assert(left->id == right->id); - assert_eq_slice(&left->schema, &right->schema); + assert_eq_string(&left->schema, &right->schema); } void assert_eq_value(const _z_value_t *left, const _z_value_t *right) { assert_eq_encoding(&left->encoding, &right->encoding); diff --git a/version.txt b/version.txt new file mode 100644 index 000000000..bd2666abb --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +1.0.0.0 \ No newline at end of file