From 8e7978dfcb4fc9091e9fbe638a0715fc672843c2 Mon Sep 17 00:00:00 2001 From: Sehong Na Date: Sat, 31 May 2014 12:32:28 +0900 Subject: [PATCH] Initialize Tizen 2.3 --- .gitignore | 21 + AUTHORS | 4 + CMakeLists.txt | 56 + LICENSE | 204 +++ README | 4 + TC/build.sh | 20 + TC/execute.sh | 20 + TC/tet_code | 12 + TC/tet_scen | 7 + TC/tetbuild.cfg | 3 + TC/tetclean.cfg | 2 + TC/tetexec.cfg | 1 + TC/unit/Makefile | 22 + TC/unit/tc_gen.sh | 28 + TC/unit/tslist | 10 + TC/unit/utc_ApplicationFW_bundle_add_func.c | 116 ++ TC/unit/utc_ApplicationFW_bundle_create_func.c | 93 ++ TC/unit/utc_ApplicationFW_bundle_decode_func.c | 111 ++ TC/unit/utc_ApplicationFW_bundle_del_func.c | 133 ++ TC/unit/utc_ApplicationFW_bundle_dup_func.c | 100 ++ TC/unit/utc_ApplicationFW_bundle_encode_func.c | 104 ++ TC/unit/utc_ApplicationFW_bundle_free_func.c | 87 ++ TC/unit/utc_ApplicationFW_bundle_get_count_func.c | 98 ++ TC/unit/utc_ApplicationFW_bundle_get_val_func.c | 116 ++ TC/unit/utc_ApplicationFW_bundle_iterate_func.c | 109 ++ TC/unit/utc_MODULE_API_func.c.in | 65 + bundle.manifest | 5 + bundle.pc.in | 12 + debian/changelog | 239 ++++ debian/compat | 1 + debian/control | 24 + debian/libbundle-0.install.in | 1 + debian/libbundle-dev.install.in | 2 + debian/rules | 126 ++ doc/bundle_doc.h | 34 + image/SLP_bundle_PG_image01.png | Bin 0 -> 19063 bytes image/SLP_bundle_PG_images_encode_decode.png | Bin 0 -> 32861 bytes image/SLP_bundle_PG_images_export_import.png | Bin 0 -> 32210 bytes image/SLP_bundle_PG_images_logical_view.png | Bin 0 -> 30128 bytes include/SLP_bundle_PG.h | 163 +++ include/bundle.h | 968 ++++++++++++++ include/bundle_log.h | 42 + include/keyval.h | 80 ++ include/keyval_array.h | 52 + include/keyval_type.h | 50 + packaging/bundle.spec | 55 + src/bundle.c | 955 +++++++++++++ src/keyval.c | 248 ++++ src/keyval_array.c | 337 +++++ src/keyval_type.c | 73 + test.sh | 11 + test/CMakeLists.txt | 11 + test/Makefile | 10 + test/TC_bundle.c | 1478 +++++++++++++++++++++ test/test_bundle.c | 288 ++++ 55 files changed, 6811 insertions(+) create mode 100755 .gitignore create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README create mode 100755 TC/build.sh create mode 100755 TC/execute.sh create mode 100755 TC/tet_code create mode 100755 TC/tet_scen create mode 100755 TC/tetbuild.cfg create mode 100755 TC/tetclean.cfg create mode 100755 TC/tetexec.cfg create mode 100644 TC/unit/Makefile create mode 100755 TC/unit/tc_gen.sh create mode 100644 TC/unit/tslist create mode 100644 TC/unit/utc_ApplicationFW_bundle_add_func.c create mode 100644 TC/unit/utc_ApplicationFW_bundle_create_func.c create mode 100644 TC/unit/utc_ApplicationFW_bundle_decode_func.c create mode 100644 TC/unit/utc_ApplicationFW_bundle_del_func.c create mode 100644 TC/unit/utc_ApplicationFW_bundle_dup_func.c create mode 100644 TC/unit/utc_ApplicationFW_bundle_encode_func.c create mode 100644 TC/unit/utc_ApplicationFW_bundle_free_func.c create mode 100644 TC/unit/utc_ApplicationFW_bundle_get_count_func.c create mode 100644 TC/unit/utc_ApplicationFW_bundle_get_val_func.c create mode 100644 TC/unit/utc_ApplicationFW_bundle_iterate_func.c create mode 100644 TC/unit/utc_MODULE_API_func.c.in create mode 100644 bundle.manifest create mode 100644 bundle.pc.in create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100755 debian/control create mode 100644 debian/libbundle-0.install.in create mode 100644 debian/libbundle-dev.install.in create mode 100755 debian/rules create mode 100755 doc/bundle_doc.h create mode 100755 image/SLP_bundle_PG_image01.png create mode 100644 image/SLP_bundle_PG_images_encode_decode.png create mode 100644 image/SLP_bundle_PG_images_export_import.png create mode 100644 image/SLP_bundle_PG_images_logical_view.png create mode 100755 include/SLP_bundle_PG.h create mode 100755 include/bundle.h create mode 100755 include/bundle_log.h create mode 100755 include/keyval.h create mode 100755 include/keyval_array.h create mode 100755 include/keyval_type.h create mode 100644 packaging/bundle.spec create mode 100755 src/bundle.c create mode 100755 src/keyval.c create mode 100755 src/keyval_array.c create mode 100755 src/keyval_type.c create mode 100755 test.sh create mode 100755 test/CMakeLists.txt create mode 100755 test/Makefile create mode 100755 test/TC_bundle.c create mode 100755 test/test_bundle.c diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..20effdd --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +build_log +*.log +*.pyc +usr +opt +*.o +*.os +*.exe +packages +binaries +*.ipk +*~ +.*swp +.cproject +.project +Debug +Release +cmake_tmp +*-stamp +tags +cscope.out diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..02c990c --- /dev/null +++ b/AUTHORS @@ -0,0 +1,4 @@ +Youmin Ha +Jayoun Lee +Sewook Park +Jaeho Lee diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..986321d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,56 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(bundle C) + +### Get VERSION from debian/changelog +file(STRINGS debian/changelog version_line LIMIT_COUNT 1 REGEX "(.*)") +string(REGEX REPLACE ".*\\(\([0-9]+:\)*\([0-9a-zA-Z.]*\).*\\).*" "\\2" VERSION ${version_line}) # Get version +string(REGEX REPLACE "^\([0-9]+\)\\..*" "\\1" VERSION_MAJOR ${VERSION}) # Get major version +message(STATUS "Version from debian/changelog: ${VERSION}, Major version: ${VERSION_MAJOR}") + +### Required packages +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED glib-2.0 dlog) +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +set(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +### Local include directories +include_directories(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/src) + +### Build +add_library(bundle SHARED + src/bundle.c + src/keyval_type.c + src/keyval.c + src/keyval_array.c + ) +set_target_properties(bundle PROPERTIES SOVERSION ${VERSION_MAJOR}) +set_target_properties(bundle PROPERTIES VERSION ${VERSION}) +target_link_libraries(bundle ${pkgs_LDFLAGS}) + + +### Make pkgconfig file +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/bundle.pc.in ${CMAKE_BINARY_DIR}/bundle.pc @ONLY) + + +### Install +install(TARGETS bundle + DESTINATION lib + ) +install(FILES + ${CMAKE_SOURCE_DIR}/include/bundle.h + ${CMAKE_SOURCE_DIR}/include/SLP_bundle_PG.h + DESTINATION include/ + ) +install(FILES ${CMAKE_BINARY_DIR}/bundle.pc + DESTINATION lib/pkgconfig/ + ) + + +### Test +add_subdirectory(test) + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a06208b --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. + diff --git a/README b/README new file mode 100644 index 0000000..0e81e7c --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +bundle : A simple string-based key-val dictionary + +By Youmin Ha + diff --git a/TC/build.sh b/TC/build.sh new file mode 100755 index 0000000..98ebeff --- /dev/null +++ b/TC/build.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +export TET_INSTALL_PATH=/scratchbox/tetware # local tetware path +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH +export TET_ROOT=$TET_TARGET_PATH + +export TET_SUITE_ROOT=`pwd` +FILE_NAME_EXTENSION=`date +%s` + +RESULT_DIR=results +HTML_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir -p $RESULT_DIR + +tcc -c -p ./ +tcc -b -j $JOURNAL_RESULT -p ./ +grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT diff --git a/TC/execute.sh b/TC/execute.sh new file mode 100755 index 0000000..2d9df79 --- /dev/null +++ b/TC/execute.sh @@ -0,0 +1,20 @@ +#!/bin/sh +#export TET_INSTALL_PATH=/mnt/nfs/tetware +export TET_INSTALL_PATH=/scratchbox/tetware +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH + +export TET_ROOT=$TET_TARGET_PATH + +export TET_SUITE_ROOT=`pwd` +FILE_NAME_EXTENSION=`date +%s` + +RESULT_DIR=results +HTML_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir -p $RESULT_DIR + +tcc -e -j $JOURNAL_RESULT -p ./ +grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT diff --git a/TC/tet_code b/TC/tet_code new file mode 100755 index 0000000..a2cf6c1 --- /dev/null +++ b/TC/tet_code @@ -0,0 +1,12 @@ +# TET reserved codes +0 "PASS" +1 "FAIL" +2 "UNRESOLVED" +3 "NOTINUSE" +4 "UNSUPPORTED" +5 "UNTESTED" +6 "UNINITIATED" +7 "NORESULT" + +# Test suite additional codes +33 "INSPECT" diff --git a/TC/tet_scen b/TC/tet_scen new file mode 100755 index 0000000..43cbc9b --- /dev/null +++ b/TC/tet_scen @@ -0,0 +1,7 @@ +all + ^TEST +##### Scenarios for TEST ##### + +# Test scenario +TEST + :include:/unit/tslist diff --git a/TC/tetbuild.cfg b/TC/tetbuild.cfg new file mode 100755 index 0000000..6192c78 --- /dev/null +++ b/TC/tetbuild.cfg @@ -0,0 +1,3 @@ +TET_OUTPUT_CAPTURE=False +TET_BUILD_TOOL=make +TET_PASS_TC_NAME=True diff --git a/TC/tetclean.cfg b/TC/tetclean.cfg new file mode 100755 index 0000000..c66eda4 --- /dev/null +++ b/TC/tetclean.cfg @@ -0,0 +1,2 @@ +TET_OUTPUT_CAPTURE=False +TET_CLEAN_TOOL=make clean diff --git a/TC/tetexec.cfg b/TC/tetexec.cfg new file mode 100755 index 0000000..0d9d39a --- /dev/null +++ b/TC/tetexec.cfg @@ -0,0 +1 @@ +TET_OUTPUT_CAPTURE=False diff --git a/TC/unit/Makefile b/TC/unit/Makefile new file mode 100644 index 0000000..2d8e954 --- /dev/null +++ b/TC/unit/Makefile @@ -0,0 +1,22 @@ +CC ?= gcc + +TARGETS = utc_ApplicationFW_bundle_create_func utc_ApplicationFW_bundle_free_func utc_ApplicationFW_bundle_add_func utc_ApplicationFW_bundle_del_func utc_ApplicationFW_bundle_get_val_func utc_ApplicationFW_bundle_get_count_func utc_ApplicationFW_bundle_dup_func utc_ApplicationFW_bundle_iterate_func utc_ApplicationFW_bundle_encode_func utc_ApplicationFW_bundle_decode_func + +PKGS = bundle + +LDFLAGS = `pkg-config --libs $(PKGS)` +LDFLAGS += $(TET_ROOT)/lib/tet3/tcm_s.o +LDFLAGS += -L$(TET_ROOT)/lib/tet3 -ltcm_s +LDFLAGS += -L$(TET_ROOT)/lib/tet3 -lapi_s + +CFLAGS = -I. `pkg-config --cflags $(PKGS)` +CFLAGS += -I$(TET_ROOT)/inc/tet3 +CFLAGS += -Wall + +all: $(TARGETS) + +$(TARGETS): %: %.c + $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) + +clean: + rm -f $(TARGETS) diff --git a/TC/unit/tc_gen.sh b/TC/unit/tc_gen.sh new file mode 100755 index 0000000..54f482d --- /dev/null +++ b/TC/unit/tc_gen.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +TMPSTR=$0 +SCRIPT=${TMPSTR##*/} + +if [ $# -lt 2 ]; then + echo "Usage) $SCRIPT module_name api_name" + exit 1 +fi + +MODULE=$1 +API=$2 +TEMPLATE=utc_MODULE_API_func.c.in +TESTCASE=utc_${MODULE}_${API}_func + +sed -e ' + s^@API@^'"$API"'^g + s^@MODULE@^'"$MODULE"'^g + ' $TEMPLATE > $TESTCASE.c + +if [ ! -e "$TESTCASE.c" ]; then + echo "Failed" + exit 1 +fi +echo "Testcase file is $TESTCASE.c" +echo "Done" +echo "please put \"$TESTCASE\" as Target in Makefile" +echo "please put \"/unit/$TESTCASE\" in tslist" diff --git a/TC/unit/tslist b/TC/unit/tslist new file mode 100644 index 0000000..3217a8f --- /dev/null +++ b/TC/unit/tslist @@ -0,0 +1,10 @@ +/unit/utc_ApplicationFW_bundle_create_func +/unit/utc_ApplicationFW_bundle_free_func +/unit/utc_ApplicationFW_bundle_add_func +/unit/utc_ApplicationFW_bundle_del_func +/unit/utc_ApplicationFW_bundle_get_val_func +/unit/utc_ApplicationFW_bundle_get_count_func +/unit/utc_ApplicationFW_bundle_dup_func +/unit/utc_ApplicationFW_bundle_iterate_func +/unit/utc_ApplicationFW_bundle_encode_func +/unit/utc_ApplicationFW_bundle_decode_func diff --git a/TC/unit/utc_ApplicationFW_bundle_add_func.c b/TC/unit/utc_ApplicationFW_bundle_add_func.c new file mode 100644 index 0000000..936d863 --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_add_func.c @@ -0,0 +1,116 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include "bundle.h" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_add_func_01(void); +static void utc_ApplicationFW_bundle_add_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_add_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_add_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of bundle_add() + */ +static void utc_ApplicationFW_bundle_add_func_01(void) +{ + int r = 0; + + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + + r = bundle_add(b, "a", "abc"); + + if (r) { + tet_infoline("bundle_add() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + + bundle_free(b); + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init bundle_add() + */ +static void utc_ApplicationFW_bundle_add_func_02(void) +{ + int r = 0; + + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + + + bundle_add(b, "abc", "def"); + r = bundle_add(b, "abc", "aaa"); + if (0 == r) { + tet_infoline("bundle_add() failed in negative test case\nduplicated key is not detected"); + tet_result(TET_FAIL); + return; + } + + r = bundle_add(b, NULL, "aaa"); + if (0 == r) { + tet_infoline("bundle_add() failed in negative test case\nNULL key is not detected"); + tet_result(TET_FAIL); + return; + } + + r = bundle_add(b, "def", NULL); + if (0 == r) { + tet_infoline("bundle_add() failed in negative test case\nNULL val is not detected"); + tet_result(TET_FAIL); + return; + } + + bundle_free(b); + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_ApplicationFW_bundle_create_func.c b/TC/unit/utc_ApplicationFW_bundle_create_func.c new file mode 100644 index 0000000..137ab37 --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_create_func.c @@ -0,0 +1,93 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include "bundle.h" + + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_create_func_01(void); +static void utc_ApplicationFW_bundle_create_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_create_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_create_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of bundle_create() + */ +static void utc_ApplicationFW_bundle_create_func_01(void) +{ + bundle *b = NULL; + + b = bundle_create(); + +/* + r = bundle_create(...); +*/ + if (NULL == b) { + tet_infoline("bundle_create() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + + if(b) bundle_free(b); + + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init bundle_create() + */ +static void utc_ApplicationFW_bundle_create_func_02(void) +{ + int r = 0; + +/* + * No argument is required +*/ + if (r) { + tet_infoline("bundle_create() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_ApplicationFW_bundle_decode_func.c b/TC/unit/utc_ApplicationFW_bundle_decode_func.c new file mode 100644 index 0000000..e84fec5 --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_decode_func.c @@ -0,0 +1,111 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include "bundle.h" +#include +#include + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_decode_func_01(void); +static void utc_ApplicationFW_bundle_decode_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_decode_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_decode_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of bundle_decode() + */ +static void utc_ApplicationFW_bundle_decode_func_01(void) +{ + int r = 0; + int len; + bundle_raw *raw = NULL; + + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + if(bundle_add(b, "a", "123")) { + tet_result(TET_UNINITIATED); + goto cleanup; + } + + r = bundle_encode(b, &raw, &len); + if(NULL == raw) { + tet_result(TET_UNINITIATED); + goto cleanup; + } + + bundle *b_dec = bundle_decode(raw, len); + if(NULL == b_dec) { + tet_result(TET_FAIL); + goto cleanup; + } + if(0 != strcmp("123", bundle_get_val(b, "a"))) { + tet_result(TET_FAIL); + goto cleanup; + } + + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + if(raw) free(raw); + return; +} + +/** + * @brief Negative test case of ug_init bundle_decode() + */ +static void utc_ApplicationFW_bundle_decode_func_02(void) +{ + if(NULL != bundle_decode(NULL, 1)) { + tet_result(TET_FAIL); + goto cleanup; + } + + tet_result(TET_PASS); +cleanup: + return; +} diff --git a/TC/unit/utc_ApplicationFW_bundle_del_func.c b/TC/unit/utc_ApplicationFW_bundle_del_func.c new file mode 100644 index 0000000..847a9fb --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_del_func.c @@ -0,0 +1,133 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include "bundle.h" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_del_func_01(void); +static void utc_ApplicationFW_bundle_del_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_del_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_del_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of bundle_del() + */ +static void utc_ApplicationFW_bundle_del_func_01(void) +{ + int r = 0; + + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + if(bundle_add(b, "a", "123")) { + tet_result(TET_UNINITIATED); + goto cleanup; + } + + r = bundle_del(b, "a"); + if (r) { + tet_infoline("bundle_del() failed in positive test case"); + tet_result(TET_FAIL); + goto cleanup; + } + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + return; +} + +/** + * @brief Negative test case of ug_init bundle_del() + */ +static void utc_ApplicationFW_bundle_del_func_02(void) +{ + int r = 0; + + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + if(bundle_add(b, "a", "123")) { + tet_result(TET_UNINITIATED); + goto cleanup; + } + + r = bundle_del(b, "a"); + if (r) { + tet_infoline("bundle_del() failed in negative test case"); + tet_result(TET_FAIL); + goto cleanup; + } + + r = bundle_del(b, "a"); + if(!r) { + tet_infoline("bundle_del() failed in negative test case"); + tet_result(TET_FAIL); + goto cleanup; + } + + r = bundle_del(b, NULL); + if(!r) { + tet_infoline("bundle_del() failed in negative test case"); + tet_result(TET_FAIL); + goto cleanup; + } + + r = bundle_del(NULL, "a"); + if(!r) { + tet_infoline("bundle_del() failed in negative test case"); + tet_result(TET_FAIL); + goto cleanup; + } + + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + return; +} diff --git a/TC/unit/utc_ApplicationFW_bundle_dup_func.c b/TC/unit/utc_ApplicationFW_bundle_dup_func.c new file mode 100644 index 0000000..34ba8ac --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_dup_func.c @@ -0,0 +1,100 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include "bundle.h" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_dup_func_01(void); +static void utc_ApplicationFW_bundle_dup_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_dup_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_dup_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of bundle_dup() + */ +static void utc_ApplicationFW_bundle_dup_func_01(void) +{ + bundle *b = NULL; + bundle *b_dup = NULL; + + b = bundle_create(); + + bundle_add(b, "aa", "bb"); + b_dup = bundle_dup(b); + + if(0 != strcmp(bundle_get_val(b, "aa"), bundle_get_val(b_dup, "aa"))) { + tet_infoline("bundle_dup() failed in positive test case"); + tet_result(TET_FAIL); + goto cleanup; + } + + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + if(b_dup) bundle_free(b_dup); + return; +} + +/** + * @brief Negative test case of ug_init bundle_dup() + */ +static void utc_ApplicationFW_bundle_dup_func_02(void) +{ + bundle *b = NULL; + + b = bundle_dup(NULL); + + if(NULL != b) { + tet_infoline("bundle_dup() failed in negative test case"); + tet_result(TET_FAIL); + goto cleanup; + } + + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + return; +} diff --git a/TC/unit/utc_ApplicationFW_bundle_encode_func.c b/TC/unit/utc_ApplicationFW_bundle_encode_func.c new file mode 100644 index 0000000..026cb0e --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_encode_func.c @@ -0,0 +1,104 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include +#include "bundle.h" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_encode_func_01(void); +static void utc_ApplicationFW_bundle_encode_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_encode_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_encode_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of bundle_encode() + */ +static void utc_ApplicationFW_bundle_encode_func_01(void) +{ + int r, len; + bundle_raw *raw = NULL; + + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + if(bundle_add(b, "a", "123")) { + tet_result(TET_UNINITIATED); + goto cleanup; + } + + r = bundle_encode(b, &raw, &len); + if(NULL == raw) { + tet_result(TET_FAIL); + goto cleanup; + } + if(len <= 0) { + tet_result(TET_FAIL); + goto cleanup; + } + + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + if(raw) free(raw); + return; +} + +/** + * @brief Negative test case of ug_init bundle_encode() + */ +static void utc_ApplicationFW_bundle_encode_func_02(void) +{ + int r = 0; + + r = bundle_encode(NULL, NULL, NULL); + if (!r) { + tet_infoline("bundle_encode() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_ApplicationFW_bundle_free_func.c b/TC/unit/utc_ApplicationFW_bundle_free_func.c new file mode 100644 index 0000000..0bd59d7 --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_free_func.c @@ -0,0 +1,87 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include "bundle.h" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_free_func_01(void); +static void utc_ApplicationFW_bundle_free_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_free_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_free_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of bundle_free() + */ +static void utc_ApplicationFW_bundle_free_func_01(void) +{ + int r; + + bundle *b; + b = bundle_create(); + r = bundle_free(b); + + if (r) { + tet_infoline("bundle_free() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init bundle_free() + */ +static void utc_ApplicationFW_bundle_free_func_02(void) +{ + int r = 0; + + r = bundle_free(NULL); + + if (0 == r) { + tet_infoline("bundle_free() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_ApplicationFW_bundle_get_count_func.c b/TC/unit/utc_ApplicationFW_bundle_get_count_func.c new file mode 100644 index 0000000..d7502cc --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_get_count_func.c @@ -0,0 +1,98 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include "bundle.h" + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_get_count_func_01(void); +static void utc_ApplicationFW_bundle_get_count_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_get_count_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_get_count_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of bundle_get_count() + */ +static void utc_ApplicationFW_bundle_get_count_func_01(void) +{ + int r; + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + if(bundle_add(b, "a", "123")) { + tet_result(TET_UNINITIATED); + goto cleanup; + } + r = bundle_get_count(b); + if(1 != r) { + tet_infoline("bundle_get_count() failed in positive test case"); + tet_result(TET_FAIL); + goto cleanup; + } + + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + return; +} + +/** + * @brief Negative test case of ug_init bundle_get_count() + */ +static void utc_ApplicationFW_bundle_get_count_func_02(void) +{ + int r; + r = bundle_get_count(NULL); + if(0 != r) { + tet_infoline("bundle_get_count() failed in negative test case"); + tet_result(TET_FAIL); + goto cleanup; + } + tet_result(TET_PASS); + +cleanup: + return; +} diff --git a/TC/unit/utc_ApplicationFW_bundle_get_val_func.c b/TC/unit/utc_ApplicationFW_bundle_get_val_func.c new file mode 100644 index 0000000..78d9e08 --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_get_val_func.c @@ -0,0 +1,116 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include "bundle.h" +#include + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_get_val_func_01(void); +static void utc_ApplicationFW_bundle_get_val_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_get_val_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_get_val_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of bundle_get_val() + */ +static void utc_ApplicationFW_bundle_get_val_func_01(void) +{ + char *ret; + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + if(bundle_add(b, "a", "123")) { + tet_result(TET_UNINITIATED); + goto cleanup; + } + ret = bundle_get_val(b, "a"); + if(0 != strcmp("123", ret)) { + tet_infoline("bundle_get_val() failed in positive test case"); + tet_result(TET_FAIL); + goto cleanup; + } + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + return; +} + +/** + * @brief Negative test case of ug_init bundle_get_val() + */ +static void utc_ApplicationFW_bundle_get_val_func_02(void) +{ + + char *ret; + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + if(bundle_add(b, "a", "123")) { + tet_result(TET_UNINITIATED); + goto cleanup; + } + ret = bundle_get_val(NULL, "a"); + if(NULL != ret) { + tet_infoline("bundle_get_val() failed in negative test case"); + tet_result(TET_FAIL); + goto cleanup; + } + ret = bundle_get_val(b, NULL); + if(NULL != ret) { + tet_infoline("bundle_get_val() failed in negative test case"); + tet_result(TET_FAIL); + goto cleanup; + } + + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + return; +} diff --git a/TC/unit/utc_ApplicationFW_bundle_iterate_func.c b/TC/unit/utc_ApplicationFW_bundle_iterate_func.c new file mode 100644 index 0000000..a773b0d --- /dev/null +++ b/TC/unit/utc_ApplicationFW_bundle_iterate_func.c @@ -0,0 +1,109 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ +#include +#include "bundle.h" +#include + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_ApplicationFW_bundle_iterate_func_01(void); +static void utc_ApplicationFW_bundle_iterate_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_ApplicationFW_bundle_iterate_func_01, POSITIVE_TC_IDX }, + { utc_ApplicationFW_bundle_iterate_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +static char *cb_val = NULL; + +static void +cb_test(const char *k, const char *v, void *data) +{ + cb_val = v; +} + +/** + * @brief Positive test case of bundle_iterate() + */ +static void utc_ApplicationFW_bundle_iterate_func_01(void) +{ + int r = 0; + + bundle *b = bundle_create(); + if(!b) { + tet_result(TET_UNINITIATED); + return; + } + if(bundle_add(b, "a", "123")) { + tet_result(TET_UNINITIATED); + goto cleanup; + } + + bundle_iterate(b, cb_test, NULL); + if (0 != strcmp(bundle_get_val(b, "a"), cb_val)) { + tet_infoline("bundle_iterate() failed in positive test case"); + tet_result(TET_FAIL); + goto cleanup; + } + + tet_result(TET_PASS); + +cleanup: + if(b) bundle_free(b); + return; +} + +/** + * @brief Negative test case of ug_init bundle_iterate() + */ +static void utc_ApplicationFW_bundle_iterate_func_02(void) +{ + int r = 0; + +/* + r = bundle_iterate(...); +*/ + if (r) { + tet_infoline("bundle_iterate() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/TC/unit/utc_MODULE_API_func.c.in b/TC/unit/utc_MODULE_API_func.c.in new file mode 100644 index 0000000..383a897 --- /dev/null +++ b/TC/unit/utc_MODULE_API_func.c.in @@ -0,0 +1,65 @@ +#include + +static void startup(void); +static void cleanup(void); + +void (*tet_startup)(void) = startup; +void (*tet_cleanup)(void) = cleanup; + +static void utc_@MODULE@_@API@_func_01(void); +static void utc_@MODULE@_@API@_func_02(void); + +enum { + POSITIVE_TC_IDX = 0x01, + NEGATIVE_TC_IDX, +}; + +struct tet_testlist tet_testlist[] = { + { utc_@MODULE@_@API@_func_01, POSITIVE_TC_IDX }, + { utc_@MODULE@_@API@_func_02, NEGATIVE_TC_IDX }, + { NULL, 0 } +}; + +static void startup(void) +{ +} + +static void cleanup(void) +{ +} + +/** + * @brief Positive test case of @API@() + */ +static void utc_@MODULE@_@API@_func_01(void) +{ + int r = 0; + +/* + r = @API@(...); +*/ + if (r) { + tet_infoline("@API@() failed in positive test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} + +/** + * @brief Negative test case of ug_init @API@() + */ +static void utc_@MODULE@_@API@_func_02(void) +{ + int r = 0; + +/* + r = @API@(...); +*/ + if (r) { + tet_infoline("@API@() failed in negative test case"); + tet_result(TET_FAIL); + return; + } + tet_result(TET_PASS); +} diff --git a/bundle.manifest b/bundle.manifest new file mode 100644 index 0000000..97e8c31 --- /dev/null +++ b/bundle.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/bundle.pc.in b/bundle.pc.in new file mode 100644 index 0000000..aa9cb10 --- /dev/null +++ b/bundle.pc.in @@ -0,0 +1,12 @@ +# Package Information for pkg-config + +prefix=/usr +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: bundle +Description: Simple string key/val dictionary library +Version: @VERSION@ +Libs: -L${libdir} -lbundle +Cflags: -I${includedir} diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..40dcfae --- /dev/null +++ b/debian/changelog @@ -0,0 +1,239 @@ +bundle (0.1.22) unstable; urgency=low + + * Checksum added to encode/decode to enhance stability and svace defects fixed. + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.22 + + -- Jaeho Lee Fri, 17 Feb 2012 16:45:12 +0900 + +bundle (0.1.21) unstable; urgency=low + + * Updated changelog + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.21 + + -- Sewook Park Mon, 05 Dec 2011 15:58:05 +0900 + +bundle (0.1.20) unstable; urgency=low + + * Changed Boilerplate as per the guideline + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.20 + + -- Jaeho Lee Mon, 07 Nov 2011 09:57:20 +0900 + +bundle (0.1.19) unstable; urgency=low + + * Support array + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.19 + + -- Jaeho Lee Thu, 06 Oct 2011 14:53:57 +0900 + +bundle (0.1.18) unstable; urgency=low + + * Modify TC Makefile + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.18 + + -- Jaeho Lee Tue, 16 Aug 2011 14:53:16 +0900 + +bundle (0.1.17) unstable; urgency=low + + * Fix Apply code cleanup + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.17 + + -- Sewook Park Tue, 02 Aug 2011 19:11:59 +0900 + +bundle (0.1.16) unstable; urgency=low + + * Fix Boilerplate module name + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.16 + + -- Sewook Park Sat, 16 Jul 2011 13:33:11 +0900 + +bundle (0.1.15) unstable; urgency=low + + * Apply Boilerplate + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.15 + + -- Sewook Park Wed, 13 Jul 2011 17:36:38 +0900 + +bundle (0.1.14) unstable; urgency=low + + * Rollback to bundle_0.1.12 + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.14 + + -- Sewook Park Thu, 07 Jul 2011 15:25:40 +0900 + +bundle (0.1.13) unstable; urgency=low + + * Check ENOMEM when adding a value in a bundle + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.13 + + -- Youmin Ha Thu, 21 Apr 2011 10:52:49 +0900 + +bundle (0.1.12) unstable; urgency=low + + * Add bundle_export_to_argv(), bundle_import_from-argv() + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.12 + + -- Youmin Ha Mon, 28 Feb 2011 09:33:57 +0900 + +bundle (0.1.11-3) unstable; urgency=low + + * reupload + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.11-3 + + -- Youmin Ha Wed, 19 Jan 2011 11:13:57 +0900 + +bundle (0.1.11-2) unstable; urgency=low + + * fix git path + * Git: 165.213.180.234:slp/pkgs/b/bundle + * Tag: bundle_0.1.11-2 + + -- Youmin Ha Wed, 19 Jan 2011 10:38:28 +0900 + +bundle (0.1.11-1) unstable; urgency=low + + * add {0, NULL} as last item to the tclist + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.11-1 + + -- Youmin Ha Wed, 19 Jan 2011 08:36:04 +0900 + +bundle (0.1.11) unstable; urgency=low + + * remove garbages from src pkg + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.11 + + -- Youmin Ha Wed, 24 Nov 2010 17:48:57 +0900 + +bundle (0.1.10-1) unstable; urgency=low + + * Add doxygen + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.10-1 + + -- Youmin Ha Fri, 05 Nov 2010 14:13:58 +0900 + +bundle (0.1.10) unstable; urgency=low + + * Add doxygen + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.10 + + -- Youmin Ha Tue, 02 Nov 2010 16:57:33 +0900 + +bundle (0.1.9) unstable; urgency=low + + * Apply SOVERSION + VERSION automatically + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.9 + + -- Youmin Ha Wed, 20 Oct 2010 19:24:28 +0900 + +bundle (0.1.8-3) unstable; urgency=low + + * Fix doxygen + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.8-3 + + -- Youmin Ha Mon, 18 Oct 2010 19:58:08 +0900 + +bundle (0.1.8-2) unstable; urgency=low + + * Fix doxygen + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.8-2 + + -- Youmin Ha Mon, 18 Oct 2010 11:05:06 +0900 + +bundle (0.1.8-1) unstable; urgency=low + + * Add libglib2.0-dev to build-dep + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.8-1 + + -- Youmin Ha Sat, 18 Sep 2010 17:16:52 +0900 + +bundle (0.1.8) unstable; urgency=low + + * Use base64 encoding/decoding with bundle_encode(), bundle_decode() + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.8 + + -- Youmin Ha Sat, 18 Sep 2010 16:47:29 +0900 + +bundle (0.1.7) unstable; urgency=low + + * add TC + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.7 + + -- Youmin Ha Wed, 08 Sep 2010 17:22:15 +0900 + +bundle (0.1.6) unstable; urgency=low + + * Include PG into dev package + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.6 + + -- Youmin Ha Fri, 27 Aug 2010 15:26:31 +0900 + +bundle (0.1.5) unstable; urgency=low + + * add programming guide into doxygen + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.5 + + -- Youmin Ha Tue, 24 Aug 2010 19:04:10 +0900 + +bundle (0.1.4) unstable; urgency=low + + * add bundle_dup() function + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.4 + + -- Youmin Ha Tue, 27 Jul 2010 14:04:52 +0900 + +bundle (0.1.3) unstable; urgency=low + + * add bundle_del() function, and many tests for wrong uses + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.3 + + -- Youmin Ha Fri, 23 Jul 2010 11:21:32 +0900 + +bundle (0.1.2) unstable; urgency=low + + * Create libbundle.so.0 and its symlink libbundle.so + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.2 + + -- Youmin Ha Thu, 22 Jul 2010 11:22:13 +0900 + +bundle (0.1.1) unstable; urgency=low + + * Fix CMakeList.txt : add @ONLY option to the command generating pc file + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.1 + + -- Youmin Ha Thu, 22 Jul 2010 09:49:54 +0900 + +bundle (0.1.0) unstable; urgency=low + + * Initial release. + * Git: 165.213.180.234:/git/slp/pkgs/bundle + * Tag: bundle_0.1.0 + + -- Youmin Ha Wed, 21 Jul 2010 17:04:19 +0900 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100755 index 0000000..9db2a05 --- /dev/null +++ b/debian/control @@ -0,0 +1,24 @@ +Source: bundle +Section: devel +Priority: extra +Maintainer: Garima , Jayoun Lee , Sewook Park , Jaeho Lee +Build-Depends: debhelper (>= 4.0.0), libglib2.0-dev, dlog-dev +Standards-Version: 0.1.0 + +Package: libbundle-0 +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Simple string key-val dictionary ADT + +Package: libbundle-dev +Architecture: any +Depends: libbundle-0 (= ${Source-Version}) +Description: Dev package for libbundle-0 +XB-Generate-Docs: yes + +Package: libbundle-dbg +Section: debug +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libbundle-0 (= ${Source-Version}) +Description: Debug symbols for libbundle-0 + diff --git a/debian/libbundle-0.install.in b/debian/libbundle-0.install.in new file mode 100644 index 0000000..bf766f0 --- /dev/null +++ b/debian/libbundle-0.install.in @@ -0,0 +1 @@ +@PREFIX@/lib/*.so* diff --git a/debian/libbundle-dev.install.in b/debian/libbundle-dev.install.in new file mode 100644 index 0000000..0f2a4da --- /dev/null +++ b/debian/libbundle-dev.install.in @@ -0,0 +1,2 @@ +@PREFIX@/include/* +@PREFIX@/lib/pkgconfig/*.pc diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..a868b66 --- /dev/null +++ b/debian/rules @@ -0,0 +1,126 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) +DEB_HOST_ARCH_OS ?= $(shell dpkg-architecture -qDEB_HOST_GNU_OS) + +CFLAGS ?= -Wall -g +LDFLAGS ?= +PREFIX ?= /usr +DATADIR ?= /opt + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +# architecture is not arm +ifneq (, $(findstring arm, $(DEB_HOST_ARCH))) + # do something here +else + # do something here for arm +endif + +CFLAGS += -fvisibility=hidden -fPIC +LDFLAGS += -Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed + +CMAKE_TMP_DIR = $(CURDIR)/cmake_tmp + +config.status: + +configure: configure-stamp + +configure-stamp: + dh_testdir + mkdir -p $(CMAKE_TMP_DIR); + export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(CMAKE_TMP_DIR) && cd $(CMAKE_TMP_DIR); CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" cmake .. -DCMAKE_INSTALL_PREFIX=$(PREFIX) + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + # Add here commands to compile the package. + cd $(CMAKE_TMP_DIR) && $(MAKE) all + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + cat $$f > $${f%.in}; \ + sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \ + sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \ + done + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f *-stamp + + rm -rf $(CMAKE_TMP_DIR) + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + rm -f $${f%.in}; \ + done + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/ncurses. + cd $(CMAKE_TMP_DIR) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples + dh_install --list-missing --sourcedir=debian/tmp +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip --dbg-package=libbundle-dbg + dh_compress + dh_fixperms +# dh_perl + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/doc/bundle_doc.h b/doc/bundle_doc.h new file mode 100755 index 0000000..546903d --- /dev/null +++ b/doc/bundle_doc.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed 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. + */ + + +#ifndef __TIZEN_CORE_LIB_BUNDLE_DOC_H__ +#define __TIZEN_CORE_LIB_BUNDLE_DOC_H__ + +/** + * @ingroup CORE_LIB_GROUP + * @defgroup CORE_LIB_BUNDLE_MODULE + * @brief A simple string-based dictionary ADT. + * + * @section CORE_LIB_BUNDLE_MODULE_HEADER Required Header + * \#include + * + * @section CORE_LIB_BUNDLE_MODULE_OVERVIEW Overview + * Bundle is a string based Dictionary ADT. A dictionary is an ordered or unordered list of key element pairs, where keys are used to locate elements in the list. +* +*/ + +#endif /* __TIZEN_CORE_LIB_BUNDLE_DOC_H__ */ \ No newline at end of file diff --git a/image/SLP_bundle_PG_image01.png b/image/SLP_bundle_PG_image01.png new file mode 100755 index 0000000000000000000000000000000000000000..3dd18deb8dcd223b0472cb08174f442168dbf57a GIT binary patch literal 19063 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 Aw*UYD literal 0 HcmV?d00001 diff --git a/image/SLP_bundle_PG_images_encode_decode.png b/image/SLP_bundle_PG_images_encode_decode.png new file mode 100644 index 0000000000000000000000000000000000000000..96cc7257a7a4d0c682967b5300e2d4adc7d7e8ef GIT binary patch literal 32861 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∨hP|J_2gQx^8HNkbGQ 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 literal 0 HcmV?d00001 diff --git a/include/SLP_bundle_PG.h b/include/SLP_bundle_PG.h new file mode 100755 index 0000000..65993de --- /dev/null +++ b/include/SLP_bundle_PG.h @@ -0,0 +1,163 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + +/** + * + * @ingroup SLP_PG + * @defgroup bundle_PG Bundle + * @brief A simple string-based dictionary ADT + * @{ + +

Introduction

+ +

Bundle is a string based Dictionary ADT. A dictionary is an ordered or unordered list of key element pairs, where keys are used to locate elements in the list.


+ +

ADT(Abstract data type) An Abstract Data type is defined as a mathematical model of the data objects that make up a data type as well +as the functions that operate on these objects.

+ +

Features

+
    +
  • Bundle provides string based Dictionary ADT to + map/store key-value pairs. Eg. Clock
  • +
  • Bundle provides Application Data Exchange (ADE): +
      +
    • Transfer application argument between caller and callee by creating a bundle and storing key-value pairs in it.
    • +
    • This bundle object can be passed between applications by encoding and decoding the bundle objects.
    • +
  • + +
+ +

Properties

+
    +
  • Only string type is allowed for key and value.
  • +
  • Each key and value is duplicated into the bundle object.
  • +
  • Unlimited number of key/value pairs. (Memory limit is still to be considered)
  • +
  • No key overlap : You cannot assign new values with existing key.
  • +
+ +

Bundle Logical View diagram

+\image html SLP_bundle_PG_images_logical_view.png "Picture 1. Logical view" + + +

Functional architecture diagram

+\image html SLP_bundle_PG_image01.png "Picture 2. Functional architecture" + +

Bundle requests are received by the Bundle interface. It passes the requests to bundle manager. Bundle Manager checks the type of the request and handles it accordingly. If string key-value needs to be handled in the request it interacts with String manager to provide the required functionality. If the request is based on array of string key-value pair then, Bundle manager interacts with Array manager to provide the required functionality.

+ +

Bundle encode decode life cycle

+\image html SLP_bundle_PG_images_encode_decode.png "Picture 2. Encode decode life cycle" + +

Bundle export import life cycle

+\image html SLP_bundle_PG_images_export_import.png "Picture 2. Export import life cycle" + +

API list and description

+
    +
  • bundle_create() : Create a bundle object.
  • +
  • bundle_free() : Free a bundle object.
  • +
  • bundle_add() : Add a key/value pair into the bundle object.
  • +
  • bundle_del() : Delete a key/value pair by given key from the bundle object.
  • +
  • bundle_get_val() : Get a value by key.
  • +
  • bundle_get_count() : Get number of key/value pairs in the bundle object.
  • +
  • bundle_dup() : Duplicate give bundle object
  • +
  • bundle_iterate() : Run iterator function for each key/value pair in the bundle object.
  • +
  • bundle_encode() : Encode bundle object into a byte code.
  • +
  • bundle_decode() : Decode byt code into a bundle object.
  • +
  • +
+ +

Programming Guide

+

bundle library is very easy to use, and the sample code below would enough to understand how to use bundle.


+

Detailed API instructions are in API reference in doxygen document.

+

Note

+
    +
  • Only string type(char *) keys/values are allowed.
  • +
  • A bundle object must be freed certainly by bundle_free().
  • +
  • Values retrived by bundle_get_val() cannot be modified.
    If you want to modify value string, duplicate it.
  • +
+

Header file

+

header file name: bundle.h

+

Code

+@code +#include +#include + +// This is a sample iterator callback function +void print_bundle_item(const char *key, const char *val, void *data); + +// Sample code +int +main(int argc, char **argv) +{ + char *str; + int count; + + bundle *b, *b_dup; + + // Create a new bundle object + b = bundle_new(); + + // Add a string with key "a" + bundle_add(b, "a", "123abc"); + + // Add another string with key "b" + bundle_add("b", "456def"); + + // str = "123abc" + // You cannot modify string! + str = bundle_get_val(b, "a"); + + // Run iterator function with each items + bundle_iterate(b, print_bundle_item, NULL); + + // count = 2 + count = bundle_get_count(b); + + // Delete an item with key "a" + bundle_del(b, "a"); + + // count = 1 + count = bundle_get_count(b); + + // If "a" key is requested, NULL is returned + // str = NULL, errno = ENOKEY + str = bundle_get_val(b, "a"); + + // Duplicate bundle object + b_dup = bundle_dup(b); + + // Free bundle objects + bundle_free(b); + bundle_free(b_dup); + + return 0; +} + +void +print_bundle_item(const char *key, const char *val, void *data) +{ + printf("%s -> %s\n", key, val); +} +@endcode + + * @} + */ diff --git a/include/bundle.h b/include/bundle.h new file mode 100755 index 0000000..39c4858 --- /dev/null +++ b/include/bundle.h @@ -0,0 +1,968 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + +#ifndef __BUNDLE_H__ +#define __BUNDLE_H__ + +/** + * @file bundle.h + * @version 0.1 + * @brief This file declares API of bundle library + */ + +/** + * @addtogroup CORE_LIB_BUNDLE_MODULE + * @{ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +# endif + +#define API __attribute__((visibility("default"))) +#define likely(x) __builtin_expect(x,1) +#define unlikely(x) __builtin_expect(x,0) + +/** + * bundle is an opaque type pointing a bundle object + */ +typedef struct _bundle_t bundle; + +/** + * bundle_raw is an encoded data type + * @see bundle_encode() + * @see bundle_decode() + */ +typedef unsigned char bundle_raw; + + +/** + * Each bundle keyval have a type. + */ +enum bundle_type_property { + BUNDLE_TYPE_ARRAY = 0x0100, + BUNDLE_TYPE_PRIMITIVE = 0x0200, + BUNDLE_TYPE_MEASURABLE = 0x0400 +}; + +enum bundle_type { + BUNDLE_TYPE_NONE = -1, + BUNDLE_TYPE_ANY = 0, + BUNDLE_TYPE_STR = 1 | BUNDLE_TYPE_MEASURABLE, /* Default */ + BUNDLE_TYPE_STR_ARRAY = BUNDLE_TYPE_STR | BUNDLE_TYPE_ARRAY | BUNDLE_TYPE_MEASURABLE, + BUNDLE_TYPE_BYTE = 2, + BUNDLE_TYPE_BYTE_ARRAY = BUNDLE_TYPE_BYTE | BUNDLE_TYPE_ARRAY +}; + +/** + * A keyval object in a bundle. + * @see bundle_iterator_t + */ +typedef struct keyval_t bundle_keyval_t; + + +/** + * bundle_iterator is a new iterator function type for bundle_foreach() + * @see bundle_foreach() + */ +typedef void (*bundle_iterator_t) ( + const char *key, + const int type, + const bundle_keyval_t *kv, + void *user_data +); + + +/** + * bundle_iterate_cb_t is an iterator function type for bundle_iterate() + * @see bundle_iterate() + * @remark This type is obsolete. Do not use this type any more. + */ +typedef void (*bundle_iterate_cb_t) (const char *key, const char *val, void *data); + + +/** + * @brief Create a bundle object. + * @pre None + * @post None + * @see bundle_free() + * @return bundle object + * @retval NULL on failure creating an object + * @remark When NULL is returned, errno is set to one of the following values; \n + * ENOMEM : No memory to create an object + * + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_free(b); // free bundle + @endcode + */ +API bundle* bundle_create(void); + +/** + * @brief Free given bundle object with key/values in it + * @pre b must be a valid bundle object. + * @post None + * @see bundle_create() + * @param[in] b bundle object to be freed + * @return Operation result; + * @retval 0 success + * @retval -1 failure + * @remark None + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_free(b); // free bundle + @endcode + */ +API int bundle_free(bundle *b); +/** + * @brief Add a string array type key-value pair into bundle. + * @pre b must be a valid bundle object. + * @post None + * @see bundle_get_str_array() + * @see bundle_set_str_array_element() + * @param[in] b bundle object + * @param[in] key key + * @param[in] str_array string type value. If NULL, empty array is created. You can change an item with + * @param[in] len Length of array. + * @return Operation result + * @retval 0 success + * @retval -1 failure + * + * @remark When -1 is returned, errno is set to one of the following values; \n + EKEYREJECTED : key is rejected (NULL or sth) \n + EPERM : key is already exist, not permitted to overwrite value \n + EINVAL : b or val is not valid (NULL or sth) \n + @code + #include + char *sa = { "aaa", "bbb", "ccc" }; // A string array of length 3 + bundle *b = bundle_create(); + bundle_add_str_array(b, "foo", sa, 3); // add a key-val pair + bundle_free(b); + @endcode + */ +API int bundle_add_str_array(bundle *b, const char *key, const char **str_array, const int len); +/** + * @brief Add a string type key-value pair into bundle. + * @pre b must be a valid bundle object. + * @post None + * @see bundle_add_str() + * @param[in] b bundle object + * @param[in] key key + * @param[in] val value + * @return Operation result + * @retval 0 success + * @retval -1 failure + * + * @remark When -1 is returned, errno is set to one of the following values; \n + EKEYREJECTED : key is rejected (NULL or sth) \n + EPERM : key is already exist, not permitted to overwrite value \n + EINVAL : b or val is not valid (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "foo_key", "bar_val"); // add a key-val pair + + bundle_free(b); + @endcode + */ +API int bundle_add(bundle *b, const char *key, const char *val); + +/** + * @brief Delete val with given key + * @pre b must be a valid bundle object. + * @post None + * @see None + * @param[in] b bundle object + * @param[in] key given key + * @return Operation result + * @retval 0 Success + * @retval -1 Failure + * + * @remark When -1 is returned, errno is set to one of the following values; \n + EINVAL : b is invalid (NULL or sth) \n + ENOKEY : No key exist \n + EKEYREJECTED : key is invalid (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "foo_key", "bar_val"); // add a key-val pair + bundle_del(b, "foo_key"); // del "foo_key" from b + + bundle_free(b); + @endcode + */ +API int bundle_del(bundle *b, const char* key); +/** + * @brief Get string array value from key + * @pre b must be a valid bundle object. + * @post None + * @see bundle_add_str_array() + * @see bundle_set_str_array_element() + * @param[in] b bundle object + * @param[in] key key + * @param[out] len array length + * @return Pointer to array of string + * @retval NULL If key is not found, returns NULL. + * @remark DO NOT free or modify returned string! + When NULL is returned, errno is set to one of the following values; \n + EINVAL : b is invalid \n + ENOKEY : No key exists \n + EKEYREJECTED : invalid key (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); + bundle_add_str_array(b, "foo", NULL, 3); // add a key-val pair + bundle_set_str_array_element(b, "foo", 0, "aaa"); + bundle_set_str_array_element(b, "foo", 1, "bbb"); + bundle_set_str_array_element(b, "foo", 2, "ccc"); + + char **str_array = NULL; + int len_str_array = 0; + + str_array=bundle_get_str_array(b, "foo", &len_str_array); + // str_array = { "aaa", "bbb", "ccc" }, and len_str_array = 3 + + bundle_free(b); + @endcode + */ + +API const char** bundle_get_str_array(bundle *b, const char *key,int *len); +/** + * @brief Get value from key + * @pre b must be a valid bundle object. + * @post None + * @see bundle_get_str() + * @param[in] b bundle object + * @param[in] key key + * @return Pointer for value string + * @retval NULL If key is not found, returns NULL. + * @remark DO NOT free or modify returned string! + When NULL is returned, errno is set to one of the following values; \n + EINVAL : b is invalid \n + ENOKEY : No key exists \n + EKEYREJECTED : invalid key (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "foo_key", "bar_val"); // add a key-val pair + char *val = bundle_get_val(b, "foo_key"); // val = "bar_val" + + bundle_free(b); // After freeing b, val becomes a dangling pointer. + val = NULL; + @endcode + */ +API const char* bundle_get_val(bundle *b, const char *key); + +/** + * @brief Get the number of bundle items + * @pre b must be a valid bundle object. + * @post None + * @see None + * @param[in] b bundle object + * @return Number of bundle items + * @remark None + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "key1", "val1"); // add a key-val pair + int count = bundle_get_count(b); // count=1 + bundle_add(b, "key2", "val2"); // add another key-val pair + count = bundle_get_count(b); // count=2 + + bundle_free(b); + @endcode + */ +API int bundle_get_count(bundle *b); + + +/** + * @brief Get a type of a value with certain key + * @pre b must be a valid bundle object + * @post None + * @see bundle_type_t + * @param[in] b A bundle + * @param[in] key A key in bundle + * @return Type of a key in b + * @remark + @code + @endcode + */ +API int bundle_get_type(bundle *b, const char *key); + + +/** + * @brief Duplicate given bundle object + * @pre b must be a valid bundle object. + * @post None + * @see None + * @param[in] b_from bundle object to be duplicated + * @return New bundle object + * @retval NULL Failure + * @remark None + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "foo_key", "bar_val"); // add a key-val pair + bundle *b_dup = bundle_dup(b); // duplicate b + + bundle_free(b); + bundle_free(b_dup); + @endcode + */ +API bundle * bundle_dup(bundle *b_from); + +/** + * @brief iterate callback function with each key/val pairs in bundle. (NOTE: Only BUNDLE_TYPE_STR type values come!) + * @pre b must be a valid bundle object. + * @post None + * @see None + * @param[in] b bundle object + * @param[in] callback iteration callback function + * @param[in] data data for callback function + * @remark This function is obsolete, and does not give values whose types are not BUNDLE_TYPE_STR. + @code + @include + #include + void sample_cb(const char *k, const char *v, void *data) { + printf("%s -> %s\n", k, v); + } + + int main(void) { + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "k1", "v1"); // add a key-val pair + bundle_add(b, "k2", "v2"); // add a key-val pair + bundle_add(b, "k3", "v3"); // add a key-val pair + bundle_iterate(b, sample_cb, NULL); // iterate sample_cb for each key/val + return 0; + } + @endcode + */ +API void bundle_iterate(bundle *b, bundle_iterate_cb_t callback, void *cb_data); + + +/** + * @brief iterate callback function with each key/val pairs in bundle. (Supports all types of value) + * @pre b must be a valid bundle object. + * @post None + * @see bundle_keyval_get_type bundle_keyval_type_is_array bundle_keyval_get_basic_val bundle_keyval_get_array_val + * @param[in] b bundle object + * @param[in] iter iteration callback function + * @param[in] user_data data for callback function + * @remark This function supports all types. + @code + @include + #include + void sample_cb(const char *key, const int type, const bundle_keyval_t *kv, void *user_data) { + void *basic_val = NULL; + size_t basic_size = 0; + void **array_val = NULL; + int array_len = 0; + size_t *array_elem_size = NULL; + + printf("Key:%s, Type:%d\n", key, type); + if(bundle_keyval_type_is_array(kv)) { + bundle_keyval_get_array_val(kv, &array_val, &array_len, &array_elem_size); + // Do something... + } + else { + bundle_keyval_get_basic_val(kv, &basic_val, &size); + // Do something... + } + } + + int main(void) { + bundle *b = bundle_create(); // Create new bundle object + bundle_add_str(b, "k1", "v1"); // add a key-val pair + bundle_add_byte(b, "k2", "v2", 3); // add a key-val pair + char *s_arr[] = {"abc", "bcd", "cde"}; + bundle_add_str_array(b, "k3", s_arr, 3); // add a key-val pair + bundle_iterate(b, sample_cb, NULL); // iterate sample_cb for each key/val + return 0; + } + @endcode + */ +API void bundle_foreach(bundle *b, bundle_iterator_t iter, void *user_data); + + +/** + * @brief Get type for a bundle_keyval_t object. + * @pre kv must be a valid bundle_keyval_t object. + * @post None + * @see bundle_foreach + * @param[in] kv A bundle_keyval_t object + * @return Type of kv + * @retval -1 Operation failure. errno is set. + * @remark + */ +API int bundle_keyval_get_type(bundle_keyval_t *kv); + + +/** + * @brief Determine if kv is array type or not. + * @pre kv must be a valid bundle_keyval_t object. + * @post None + * @see bundle_foreach + * @param[in] kv A bundle_keyval_t object + * @return Operation result + * @retval 1 kv is an array. + * @retval 0 kv is not an array. + * @remark + */ +API int bundle_keyval_type_is_array(bundle_keyval_t *kv); + + +/** + * @brief Determine if kv is measurable type or not. + * @pre kv must be a valid bundle_keyval_t object. + * @post None + * @see bundle_foreach + * @param[in] kv A bundle_keyval_t object + * @return Operation result + * @retval 1 kv is an measurable. + * @retval 0 kv is not an measurable. + * @remark + */ +API int bundle_keyval_type_is_measurable(bundle_keyval_t *kv); + + +/** + * @brief Get value and size of the value from kv of basic type. + * @pre kv must be a valid bundle_keyval_t object. + * @post val, size are set. + * @see bundle_foreach + * @param[in] kv A bundle_keyval_t object + * @param[out] val Value + * @param[out] size Size of val + * @return Operation result + * @retval 0 Success + * @remark Do not free val. + */ +API int bundle_keyval_get_basic_val(bundle_keyval_t *kv, void **val, size_t *size); + + +/** + * @brief Get value array, length of array, and size of each array item + * @pre kv must be a valid bundle_keyval_t object. + * @post array_val, array_len, array_item_size are set. + * @see bundle_foreach + * @param[in] kv A bundle_keyval_t object + * @param[out] array_val Array pointer of values + * @param[out] array_len Length of array_val + * @param[out] array_element_size Array of size of each array element + * @return Operation result + * @retval 0 Success + * @retval 0 Failure + * @remark + */ +API int bundle_keyval_get_array_val(bundle_keyval_t *kv, void ***array_val, unsigned int *array_len, size_t **array_element_size); + + +/** + * @brief Encode bundle to bundle_raw format (uses base64 format) + * @pre b must be a valid bundle object. + * @post None + * @see None + * @param[in] b bundle object + * @param[out] r returned bundle_raw data(byte data) + * r MUST BE FREED by free(r). + * @param[out] len size of r (in bytes) + * @return size of raw data + * @retval 0 Success + * @retval -1 Failure + * @remark None + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "foo_key", "bar_val"); // add a key-val pair + bundle_raw *r; + int len; + bundle_encode(b, &r, &len); // encode b + + bundle_free_encoded_rawdata(r); + bundle_free(b); + @endcode + */ +API int bundle_encode(bundle *b, bundle_raw **r, int *len); + +/** + * @brief Free encoded rawdata from memory + * @pre r is a valid rawdata generated by bundle_encode(). + * @post None + * @see bundle_encode + * @param[in] r is a rawdata + * @return Operation result + * @retval 0 Success + * @retval -1 Failure + * @reamark None + */ +API int bundle_free_encoded_rawdata(bundle_raw **r); + +/** + * @brief deserialize bundle_raw, and get bundle object + * @pre b must be a valid bundle object. + * @post None + * @see None + * @param[in] r bundle_raw data to be converted to bundle object + * @param[in] len size of r + * @return bundle object + * @retval NULL Failure + * @remark None + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "foo_key", "bar_val"); // add a key-val pair + + bundle_raw *encoded_b; + int len; + bundle_encode(b, &encoded_b, &len); // encode b + + bundle *b_dup; + b_dup = bundle_decode(encoded_b, len); // decoded bundle object + + bundle_free(b); + free(encoded_b); + bundle_free(b_dup); + @endcode + */ +API bundle * bundle_decode(const bundle_raw *r, const int len); + +/** + * @brief Encode bundle to bundle_raw format + * @pre b must be a valid bundle object. + * @post None + * @see None + * @param[in] b bundle object + * @param[out] r returned bundle_raw data(byte data) + * r MUST BE FREED by free(r). + * @param[out] len size of r (in bytes) + * @return size of raw data + * @retval 0 Success + * @retval -1 Failure + * @remark None + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "foo_key", "bar_val"); // add a key-val pair + bundle_raw *r; + int len; + bundle_encode_raw(b, &r, &len); // encode b + + bundle_free_encoded_rawdata(r); + bundle_free(b); + @endcode + */ +API int bundle_encode_raw(bundle *b, bundle_raw **r, int *len); + +/** + * @brief deserialize bundle_raw, and get bundle object + * @pre b must be a valid bundle object. + * @post None + * @see None + * @param[in] r bundle_raw data to be converted to bundle object + * @param[in] len size of r + * @return bundle object + * @retval NULL Failure + * @remark None + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "foo_key", "bar_val"); // add a key-val pair + + bundle_raw *encoded_b; + int len; + bundle_encode(b, &encoded_b, &len); // encode b + + bundle *b_dup; + b_dup = bundle_decode_raw(encoded_b, len); // decoded bundle object + + bundle_free(b); + free(encoded_b); + bundle_free(b_dup); + @endcode + */ +API bundle * bundle_decode_raw(const bundle_raw *r, const int len); + +/** + * @brief Export bundle to argv + * @pre b is a valid bundle object. + * @post argv is a pointer of newly allocated memory. It must be freed. + * Each item of argv points the string in the bundle object b. If b is freed, argv will have garbage pointers. DO NOT FREE b BEFORE ACCESSING argv!! + * @see bundle_import_from_argv + * @param[in] b bundle object + * @param[out] argv Pointer of string array. + * This array has NULL values for first and last item. + * First NULL is for argv[0], and last NULL is a terminator for execv(). + * @return Number of item in argv. This value is equal to actual count of argv - 1. (Last NULL terminator is not counted.) + * @retval -1 Function failure. Check errno to get the reason. + * @remark None + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add(b, "foo_key", "bar_val"); // add a key-val pair + + int argc = 0; + char **argv = NULL; + argc = bundle_export_to_argv(b, &argv); // export to argv + if(0 > argc) error("export failure"); + + int i; + for(i=0; i < argc; i++) { + printf("%s\n", argv[i]); // print argv + } + bundle_free_exported_argv(argc, argv); // argv must be freed after being used. + + bundle_free(b); + @endcode + */ +API int bundle_export_to_argv(bundle *b, char ***argv); + +/** + * @brief Free exported argv + * @pre argv is a valid string array generated from bundle_export_to_argv(). + * @post None + * @see bundle_export_to_argv + * @param[in] argc number of args, which is the return value of bundle_export_to_argv(). + * @param[in] argv array from bundle_export_to_argv(). + * @return Operation result. + * @retval 0 on success + * @retval -1 on failure + * @remark You must not use this API when you use global argv. + @code + bundle *b = bundle_create(); + bundle_add_str(b, "foo", "bar"); + + int argc = 0; + char **argv = NULL; + argc = bundle_export_to_argv(b, &argv); + if(0 > argc) error("export failure"); + + // Use argv... + + bundle_free_export_argv(argc, argv); + argv = NULL; + + bundle_free(b); + @endcode + */ +API int bundle_free_exported_argv(int argc, char ***argv); + +/** + * @brief import a bundle from argv + * @pre argv is a valid string array, which is created by bundle_export_to_argv(). + * @post Returned bundle b must be freed. + * @see bundle_export_to_argv + * @param[in] argc argument count + * @param[in] argv argument vector + * @return New bundle object + * @retval NULL Function failure + * @remark None + @code + #include + + int main(int argc, char **argv) { + bundle *b = bundle_import_from_argv(argc, argv); // import from argc+argv + char *val = bundle_get_val(b, "foo_key"); // value for "foo_key" + // ...... + bundle_free(b); // After freeing b, val becomes a dangling pointer. + val = NULL; + } + @endcode + */ +API bundle * bundle_import_from_argv(int argc, char **argv); + +/** + * @brief Add a string type key-value pair into bundle. + * @pre b must be a valid bundle object. + * @post None + * @see bundle_get_str() + * @param[in] b bundle object + * @param[in] key key + * @param[in] str string type value + * @return Operation result + * @retval 0 success + * @retval -1 failure + * + * @remark When -1 is returned, errno is set to one of the following values; \n + EKEYREJECTED : key is rejected (NULL or sth) \n + EPERM : key is already exist, not permitted to overwrite value \n + EINVAL : b or val is not valid (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add_str(b, "foo", "bar"); // add a key-val pair + + bundle_free(b); + @endcode + */ +API int bundle_add_str(bundle *b, const char *key, const char *str); + +/** + * @brief Set a value of string array element + * @pre b must be a valid bundle object. + * @post None + * @see bundle_add_str_array() + * @see bundle_get_str_array() + * @param[in] b bundle object + * @param[in] key key + * @param[in] idx index of array element to be changed + * @param[in] val string type value. If NULL, empty array is created. You can change an item with + * @return Operation result + * @retval 0 success + * @retval -1 failure + * + * @remark When -1 is returned, errno is set to one of the following values; \n + EKEYREJECTED : key is rejected (NULL or sth) \n + EPERM : key is already exist, not permitted to overwrite value \n + EINVAL : b or val is not valid (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); + bundle_add_str_array(b, "foo", NULL, 3); // add a key-val pair + bundle_set_str_array_element(b, "foo", 0, "aaa"); + bundle_set_str_array_element(b, "foo", 1, "bbb"); + bundle_set_str_array_element(b, "foo", 2, "ccc"); + + char **str_array = NULL; + int len_str_array = 0; + + str_array=bundle_get_str_array(b, "foo", &len_str_array); + // str_array = { "aaa", "bbb", "ccc" }, and len_str_array = 3 + + bundle_free(b); + @endcode + */ +API int bundle_set_str_array_element(bundle *b, const char *key, const unsigned int idx, const char *val); + +/** + * @brief Add a byte type key-value pair into bundle. + * @pre b must be a valid bundle object. + * @post None + * @see bundle_get_byte() + * @param[in] b bundle object + * @param[in] key key + * @param[in] byte string type value + * @param[in] size size of byte + * @return Operation result + * @retval 0 success + * @retval -1 failure + * + * @remark When -1 is returned, errno is set to one of the following values; \n + EKEYREJECTED : key is rejected (NULL or sth) \n + EPERM : key is already exist, not permitted to overwrite value \n + EINVAL : b or val is not valid (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add_byte(b, "foo", "bar\0", 4); // add a key-val pair + + bundle_free(b); + @endcode + */ + +API int bundle_add_byte(bundle *b, const char *key, const void *byte, const size_t size); + +/** + * @brief Add a byte array type key-value pair into bundle. + * @pre b must be a valid bundle object. + * @post None + * @see bundle_get_str_array() + * @see bundle_set_byte_array_element() + * @param[in] b bundle object + * @param[in] key key + * @param[in] byte_array Not used. + * @param[in] len Length of array to be created + * @return Operation result + * @retval 0 success + * @retval -1 failure + * + * @remark When -1 is returned, errno is set to one of the following values; \n + EKEYREJECTED : key is rejected (NULL or sth) \n + EPERM : key is already exist, not permitted to overwrite value \n + EINVAL : b or val is not valid (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); + bundle_add_byte_array(b, "foo", NULL, 3); // add a byte-array with length 3 + + bundle_set_byte_array_element(b, "foo", 0, "aaa\0", 4); array[0] = "aaa\0" + bundle_set_byte_array_element(b, "foo", 1, "bbb\0", 4); array[1] = "bbb\0" + bundle_set_byte_array_element(b, "foo", 2, "ccc\0", 4); array[2] = "ccc\0" + + bundle_free(b); + @endcode + */ +API int bundle_add_byte_array(bundle *b, const char *key, void **byte_array, const unsigned int len); + +/** + * @brief Set a value of byte array element + * @pre b must be a valid bundle object. + * @post None + * @see bundle_add_str_array() + * @see bundle_get_str_array() + * @param[in] b bundle object + * @param[in] key key + * @param[in] idx index of array element to be changed + * @param[in] val string type value. If NULL, empty array is created. You can change an item with + * @param[in] size Size of value in byte + * @return Operation result + * @retval 0 success + * @retval -1 failure + * + * @remark When -1 is returned, errno is set to one of the following values; \n + EKEYREJECTED : key is rejected (NULL or sth) \n + EPERM : key is already exist, not permitted to overwrite value \n + EINVAL : b or val is not valid (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); + bundle_add_byte_array(b, "foo", NULL, 3); // add a key-val pair + bundle_set_byte_array_element(b, "foo", 0, "aaa\0", 4); + bundle_set_byte_array_element(b, "foo", 1, "bbb\0", 4); + bundle_set_byte_array_element(b, "foo", 2, "ccc\0", 4); + + unsigned char **byte_array = NULL; + int len_byte_array = 0; + + byte_array=bundle_get_str_array(b, "foo", &len_byte_array); + // byte_array = { "aaa\0", "bbb\0", "ccc\0" }, and len_byte_array = 3 + + bundle_free(b); + @endcode + */ +API int bundle_set_byte_array_element(bundle *b, const char *key, const unsigned int idx, const void *val, const size_t size); + +/** + * @brief Get string value from key + * @pre b must be a valid bundle object. + * @post None + * @see bundle_add_str() + * @param[in] b bundle object + * @param[in] key key + * @param[out] str returned value + * @return Operation result + * @retval 0 on success + * @retval -1 on failure + * @remark Do not free str! + When -1 is returned, errno is set to one of the following values; \n + EINVAL : b is invalid \n + ENOKEY : No key exists \n + EKEYREJECTED : invalid key (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add_str(b, "foo_key", "bar_val"); // add a key-val pair + + char *v = NULL; + bundle_get_str(b, "foo_key", &v); // v = "bar_val" + + bundle_free(b); // After freeing b, v becomes a dangling pointer. + v = NULL; + @endcode + */ +API int bundle_get_str(bundle *b, const char *key, char **str); + +/** + * @brief Get byte value from key + * @pre b must be a valid bundle object. + * @post None + * @see bundle_add_byte() + * @param[in] b bundle object + * @param[in] key key + * @param[out] byte returned value + * @param[out] size Size of byte + * @return Operation result + * @retval 0 on success + * @retval -1 on failure + * @remark Do not free str! + When -1 is returned, errno is set to one of the following values; \n + EINVAL : b is invalid \n + ENOKEY : No key exists \n + EKEYREJECTED : invalid key (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); // Create new bundle object + bundle_add_byte(b, "foo", "bar\0", 4); // add a key-val pair + + unsigned char *v = NULL; + bundle_get_str(b, "foo", &v); // v = "bar\0" + + bundle_free(b); // After freeing b, v becomes a dangling pointer. + @endcode + */ +API int bundle_get_byte(bundle *b, const char *key, void **byte, size_t *size); + +/** + * @brief Get byte array value from key + * @pre b must be a valid bundle object. + * @post None + * @see bundle_add_str_array() + * @see bundle_set_str_array_element() + * @param[in] b bundle object + * @param[in] key key + * @param[out] byte_array returned value + * @param[out] len array length + * @param[out] array_element_size an array of sizes of each byte_array element + * @return Operation result + * @retval 0 on success + * @retval -1 on failure + * @remark Do not free str! + When -1 is returned, errno is set to one of the following values; \n + EINVAL : b is invalid \n + ENOKEY : No key exists \n + EKEYREJECTED : invalid key (NULL or sth) \n + @code + #include + bundle *b = bundle_create(); + bundle_add_byte_array(b, "foo", NULL, 3); + bundle_set_byte_array_element(b, "foo", 0, "aaa\0", 4); + bundle_set_byte_array_element(b, "foo", 1, "bbb\0", 4); + bundle_set_byte_array_element(b, "foo", 2, "ccc\0", 4); + + char **byte_array = NULL; + int len_byte_array = 0; + size_t *size_byte_array = NULL; + + byte_array = bundle_get_str_array(b, "foo", &len_byte_array, &size_byte_array); + // byte_array = { "aaa\0", "bbb\0", "ccc\0" }, len_byte_array = 3, and size_byte_array = { 4, 4, 4 } + + bundle_free(b); + @endcode + */ +API int bundle_get_byte_array(bundle *b, const char *key, void ***byte_array, unsigned int *len, unsigned int **array_element_size); + + +#ifdef __cplusplus +} +#endif + +/** + * @} + * @} + */ + +#endif /* __BUNDLE_H__ */ diff --git a/include/bundle_log.h b/include/bundle_log.h new file mode 100755 index 0000000..192c283 --- /dev/null +++ b/include/bundle_log.h @@ -0,0 +1,42 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + +#include +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "BUNDLE" + +#ifdef _DEBUG_MODE_ +#define BUNDLE_LOG_PRINT(FMT, ARG...) do { printf("%5d", getpid()); printf + ("%s() : "FMT"\n", __FUNCTION__, ##ARG); } while (false) +#define BUNDLE_EXCEPTION_PRINT(FMT, ARG...) do { printf("%5d", getpid()); + printf("%s() : "FMT"\n", __FUNCTION__, ##ARG); } while (false) +#define BUNDLE_ASSERT_PRINT(FMT, ARG...) do { printf("%5d", getpid()); printf + ("%s() : "FMT"\n", __FUNCTION__, ##ARG); } while (false) +#else +#define BUNDLE_LOG_PRINT(FMT, ARG...) SLOGD(FMT, ##ARG); +#define BUNDLE_EXCEPTION_PRINT(FMT, ARG...) SLOGW(FMT, ##ARG); +#define BUNDLE_ASSERT_PRINT(FMT, ARG...) SLOGE(FMT, ##ARG); +#endif diff --git a/include/keyval.h b/include/keyval.h new file mode 100755 index 0000000..ce1e7f8 --- /dev/null +++ b/include/keyval.h @@ -0,0 +1,80 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + +#ifndef __KEYVAL_H__ +#define __KEYVAL_H__ + +/** + * keyval.h + * + * keyval object + */ + +#include + +// ADT: object +typedef struct keyval_t keyval_t; + +// Object methods +typedef struct keyval_method_collection_t keyval_method_collection_t; + +typedef void (*keyval_method_free_t)(keyval_t *kv, int do_free_object); +typedef int (*keyval_method_compare_t) (keyval_t *kv1, keyval_t *kv2); +typedef size_t (*keyval_method_get_encoded_size_t)(keyval_t *kv); +typedef size_t (*keyval_method_encode_t)(keyval_t *, unsigned char **byte, size_t *byte_len); +typedef size_t (*keyval_method_decode_t)(unsigned char *byte, keyval_t **kv); + + +struct keyval_method_collection_t +{ + keyval_method_free_t free; + keyval_method_compare_t compare; + keyval_method_get_encoded_size_t get_encoded_size; + keyval_method_encode_t encode; + keyval_method_decode_t decode; +}; + +struct keyval_t +{ + int type; + char *key; // To be freed. + void *val; // To be freed. + size_t size; // Size of a single value. + struct keyval_t *next; + + keyval_method_collection_t *method; + +}; + + +keyval_t * keyval_new(keyval_t *kv, const char *key, const int type, const void *val, const size_t size); +void keyval_free(keyval_t *kv, int do_free_object); +int keyval_compare(keyval_t *kv1, keyval_t *kv2); +size_t keyval_get_encoded_size(keyval_t *kv); +size_t keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len); +size_t keyval_decode(unsigned char *byte, keyval_t **kv); +int keyval_get_data(keyval_t *kv, int *type, void **val, size_t *size); +int keyval_get_type_from_encoded_byte(unsigned char *byte); + +#endif /* __KEYVAL_H__ */ + diff --git a/include/keyval_array.h b/include/keyval_array.h new file mode 100755 index 0000000..afdf52c --- /dev/null +++ b/include/keyval_array.h @@ -0,0 +1,52 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + +/** + * keyval_array.h + * + * keyval_array object + */ + +#include "keyval.h" + + +typedef struct keyval_array_t +{ + struct keyval_t kv; // Inherits keyval_t + + unsigned int len; // length of array_val + size_t *array_element_size; // Array of size of each element + void **array_val; // Array + +} keyval_array_t; + + +keyval_array_t *keyval_array_new(keyval_array_t *kva, const char *key, const int type, const void **array_val, const unsigned int len); +void keyval_array_free(keyval_array_t *kva, int do_free_object); +int keyval_array_compare(keyval_array_t *kva1, keyval_array_t *kva2); +size_t keyval_array_get_encoded_size(keyval_array_t *kva); +size_t keyval_array_encode(keyval_array_t *kva, void **byte, size_t *byte_len); +size_t keyval_array_decode(void *byte, keyval_array_t **kva); +int keyval_array_copy_array(keyval_array_t *kva, void **array_val, unsigned int array_len, size_t (*measure_val_len)(void * val)); +int keyval_array_get_data(keyval_array_t *kva, int *type,void ***array_val, unsigned int *len, size_t **array_element_size); +int keyval_array_set_element(keyval_array_t *kva, int idx, void *val, size_t size); diff --git a/include/keyval_type.h b/include/keyval_type.h new file mode 100755 index 0000000..9561c5a --- /dev/null +++ b/include/keyval_type.h @@ -0,0 +1,50 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + +#ifndef __KEYVAL_TYPE_H__ +#define __KEYVAL_TYPE_H__ + +/** + * keyval_type.h + * + * Definitions & short funcs for keyval type + */ + +#include "bundle.h" +#include +#include + +// measure_size function type +typedef size_t (*keyval_type_measure_size_func_t) (void *val); + +void _type_init_measure_size_func(void); +int keyval_type_is_array(int type); +int keyval_type_is_measurable(int type); +keyval_type_measure_size_func_t keyval_type_get_measure_size_func(int type); + + +/* Measure functions for each type */ +size_t keyval_type_measure_size_str(void *val); +void keyval_type_init(void); + +#endif /* __KEYVAL_TYPE_H__ */ diff --git a/packaging/bundle.spec b/packaging/bundle.spec new file mode 100644 index 0000000..b4741f8 --- /dev/null +++ b/packaging/bundle.spec @@ -0,0 +1,55 @@ +Name: bundle +Summary: String key-val dictionary ADT +Version: 0.1.32 +Release: 1 +Group: System/Libraries +License: Apache License, Version 2.0 +Source0: bundle-%{version}.tar.gz +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(dlog) + +%description +Simple string key-val dictionary ADT + +%package devel +Summary: String key-val dictionary ADT (devel) +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Simple string key-val dictionary ADT (devel) + +%prep +%setup -q -n %{name}-%{version} + +%build +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +mkdir -p %{buildroot}/usr/share/license +cp LICENSE %{buildroot}/usr/share/license/%{name} + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%manifest bundle.manifest +%defattr(-,root,root,-) +%{_libdir}/libbundle.so.* +/usr/share/license/%{name} + +%files devel +%defattr(-,root,root,-) +%{_includedir}/bundle.h +%{_includedir}/SLP_bundle_PG.h +%{_libdir}/pkgconfig/bundle.pc +%{_libdir}/libbundle.so diff --git a/src/bundle.c b/src/bundle.c new file mode 100755 index 0000000..2d9902c --- /dev/null +++ b/src/bundle.c @@ -0,0 +1,955 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + + +/** + * bundle.c + */ + +#include "bundle.h" +#include "keyval.h" +#include "keyval_array.h" +#include "keyval_type.h" +#include "bundle_log.h" +#include + +#include /* calloc, free */ +#include /* strdup */ +#include + +#define CHECKSUM_LENGTH 32 +#define TAG_IMPORT_EXPORT_CHECK "`zaybxcwdveuftgsh`" +/* ADT */ +struct _bundle_t +{ + keyval_t *kv_head; +}; + + +/** + * Find a kv from bundle + */ +static keyval_t * +_bundle_find_kv(bundle *b, const char *key) +{ + keyval_t *kv; + + if(NULL == b) { errno = EINVAL; return NULL; } + if(NULL == key) { errno = EKEYREJECTED; return NULL; } + + kv = b->kv_head; + while (kv != NULL) { + if(0 == strcmp(key, kv->key)) return kv; + kv = kv->next; + } + /* Not found */ + errno = ENOKEY; + return NULL; +} + +/** + * Append kv into bundle + */ +static int +_bundle_append_kv(bundle *b, keyval_t *new_kv) +{ + keyval_t *kv; + + if (NULL == b->kv_head) b->kv_head = new_kv; + else { + kv = b->kv_head; + while (NULL != kv->next) kv = kv->next; + kv->next = new_kv; + } + return 0; +} + +static int +_bundle_add_kv(bundle *b, const char *key, const void *val, const size_t size, const int type, const unsigned int len) +{ + /* basic value check */ + if(NULL == b) { errno = EINVAL; return -1; } + if(NULL == key) { errno = EKEYREJECTED; return -1; } + if(0 == strlen(key)) { errno = EKEYREJECTED; return -1; } + + keyval_t *kv = _bundle_find_kv(b, key); + if(kv) { /* Key already exists */ + errno = EPERM; + return -1; + } + errno = 0; + + keyval_t *new_kv = NULL; + if(keyval_type_is_array(type)) { + // array type + keyval_array_t *kva = keyval_array_new(NULL, key, type, (const void **) val, len); + new_kv = (keyval_t *)kva; + } + else { + // normal type + new_kv = keyval_new(NULL, key, type, val, size); + } + if(!new_kv) { + // NOTE: errno is already set. (ENOMEM, ...) + return -1; + } + + _bundle_append_kv(b, new_kv); + + return 0; + +} + +static int +_bundle_get_val(bundle *b, const char *key, const int type, void **val, size_t *size, unsigned int *len, size_t **array_element_size) +{ + keyval_t *kv = _bundle_find_kv(b, key); + if(!kv) { /* Key doesn't exist */ + /* NOTE: errno is already set. */ + return -1; + } + if(BUNDLE_TYPE_ANY != type && type != kv->type) { + errno = ENOTSUP; + return -1; + } + + if(keyval_type_is_array(type)) { + keyval_array_t *kva = (keyval_array_t *)kv; + keyval_array_get_data(kva, NULL, (void ***)val, len, array_element_size); + } + else { + keyval_get_data(kv, NULL, val, size); + } + + return 0; +} + +/** global initialization + * Run only once. + */ +static void +_bundle_global_init(void) +{ + static int _is_done = 0; + if(_is_done) return; + + // Run init functions + keyval_type_init(); + + _is_done = 1; + return; +} + + +/* APIs */ +bundle * +bundle_create(void) +{ + bundle *b = NULL; + + _bundle_global_init(); + + b = calloc(1, sizeof(bundle)); /* fill mem with NULL */ + if(NULL == b) { + BUNDLE_EXCEPTION_PRINT("Unable to allocate memory for bundle\n"); + errno = ENOMEM; + goto EXCEPTION; + } + + return b; + +EXCEPTION: + return NULL; +} + +int +bundle_free(bundle *b) +{ + keyval_t *kv, *tmp_kv; + + if(NULL == b) { + BUNDLE_EXCEPTION_PRINT("Bundle is already freed\n"); + errno = EINVAL; + return -1; + } + + /* Free keyval list */ + kv = b->kv_head; + while(kv != NULL) { + tmp_kv = kv; + kv = kv->next; + tmp_kv->method->free(tmp_kv, 1); + } + + /* free bundle */ + free(b); + + return 0; +} +// str type +int +bundle_add_str(bundle *b, const char *key, const char *str) +{ + if(!str) { errno = EINVAL; return -1; } + return _bundle_add_kv(b, key, str, strlen(str)+1, BUNDLE_TYPE_STR, 1); +} + +int +bundle_get_str(bundle *b, const char *key, char **str) +{ + return _bundle_get_val(b, key, BUNDLE_TYPE_STR, (void **) str, NULL, NULL, NULL); +} + +int +bundle_add(bundle *b, const char *key, const char *val) +{ + return bundle_add_str(b, key, val); +} + +int +bundle_del(bundle *b, const char *key) +{ + keyval_t *kv = NULL, *prev_kv = NULL; + + /* basic value check */ + if(NULL == b) { errno = EINVAL; return -1; } + if(NULL == key) { errno = EKEYREJECTED; return -1; } + if(0 == strlen(key)) { errno = EKEYREJECTED; return -1; } + + kv = b->kv_head; + while (kv != NULL) { + if(0 == strcmp(key, kv->key)) break; + prev_kv = kv; + kv = kv->next; + } + if (NULL == kv) { errno = ENOKEY; return -1; } + else { + if(NULL != prev_kv) { + prev_kv->next = kv->next; + } + if(kv == b->kv_head) b->kv_head = kv->next; + kv->method->free(kv, 1); + } + return 0; + +} + +const char * +bundle_get_val(bundle *b, const char *key) +{ + char *val = NULL; + int r = 0; + + r = bundle_get_str(b, key, &val); + return val; + +} + +/** + * @brief used by bundle_get_count() API, to count number of items in a bundle + */ +static void +_bundle_get_count_iter(const char *k, const int type, const bundle_keyval_t *kv, void *user_data) +{ + int *count = (int *)user_data; + *count += 1; +} + +int +bundle_get_count (bundle *b) +{ + int count = 0; + if (NULL == b) return count; + bundle_foreach(b, _bundle_get_count_iter, &count); + return count; +} + +void +bundle_iterate(bundle *b, bundle_iterate_cb_t callback, void *data) +{ + keyval_t *kv = b->kv_head; + if(callback) { + while(NULL != kv) { + callback(kv->key, kv->val, data); + kv = kv->next; + } + } +} + +void +bundle_foreach(bundle *b, bundle_iterator_t iter, void *user_data) +{ + if(NULL==b) + { + return; /*TC_FIX if b=NULL- error handling */ + } + keyval_t *kv = b->kv_head; + if(iter) { + while(NULL != kv) { + iter(kv->key, kv->type, kv, user_data); + kv = kv->next; + } + } +} + +/* keyval functions */ +int +bundle_keyval_get_type(bundle_keyval_t *kv) +{ + return kv->type; +} + +int +bundle_keyval_type_is_array(bundle_keyval_t *kv) +{ + return keyval_type_is_array(kv->type); +} + +int +bundle_keyval_type_is_measurable(bundle_keyval_t *kv) +{ + return keyval_type_is_measurable(kv->type); +} + +int +bundle_keyval_get_basic_val(bundle_keyval_t *kv, void **val, size_t *size) +{ + return keyval_get_data(kv, NULL, val, size); +} + +int +bundle_keyval_get_array_val(bundle_keyval_t *kv, void ***array_val, unsigned int *array_len, size_t **array_item_size) +{ + return keyval_array_get_data((keyval_array_t *)kv, NULL, array_val, array_len, array_item_size); +} + + +/*static void +_iter_do_bundle_dup(const char *key, const void *val, const int type, const size_t size, const unsigned int len, void *user_data) +{ + //int r; + bundle *b_to = (bundle *)user_data; + + _bundle_add_kv(b_to, key, val, size, type, len); + +} +*/ +bundle * +bundle_dup(bundle *b_from) +{ + bundle *b_to = NULL; + int i; + + if(NULL == b_from) { errno = EINVAL; return NULL; } + b_to = bundle_create(); + if(NULL == b_to) return NULL; + + keyval_t *kv_from = b_from->kv_head; + keyval_t *kv_to = NULL; + while(kv_from != NULL) { + if(keyval_type_is_array(kv_from->type)) { + keyval_array_t *kva_from = (keyval_array_t *)kv_from; + kv_to = (keyval_t *) keyval_array_new(NULL, kv_from->key, kv_from->type, NULL, kva_from->len); + if(!kv_to) goto ERR_CLEANUP; + for(i=0; i < kva_from->len; i++) { + if(((keyval_array_t *)kv_from)->array_val[i]) { + keyval_array_set_element((keyval_array_t*)kv_to, i, ((keyval_array_t *)kv_from)->array_val[i], ((keyval_array_t *)kv_from)->array_element_size[i]); + } + } + _bundle_append_kv(b_to, kv_to); + } + else { + if(_bundle_add_kv(b_to, kv_from->key, kv_from->val, kv_from->size, kv_from->type, 0)) goto ERR_CLEANUP; + } + + kv_from = kv_from->next; + } + return b_to; + +ERR_CLEANUP: + bundle_free(b_to); + return NULL; +} + + +int +bundle_encode(bundle *b, bundle_raw **r, int *len) +{ + keyval_t *kv; + unsigned char *m; + unsigned char *p_m; + unsigned char *byte; + size_t byte_len; + gchar *chksum_val; + + if(NULL == b) { + errno = EINVAL; + return -1; + } + + /* calculate memory size */ + size_t msize = 0; // Sum of required size + + kv = b->kv_head; + while(kv != NULL) { + msize += kv->method->get_encoded_size(kv); + kv = kv->next; + } + m = calloc(msize+CHECKSUM_LENGTH, sizeof(unsigned char)); + if(unlikely(NULL == m )) { errno = ENOMEM; return -1; } + + p_m = m+CHECKSUM_LENGTH; /* temporary pointer */ + + kv = b->kv_head; + while(kv != NULL) { + byte = NULL; + byte_len = 0; + + kv->method->encode(kv, &byte, &byte_len); + memcpy(p_m, byte, byte_len); + + p_m += byte_len; + kv = kv->next; + + free(byte); + } + + /*compute checksum from the data*/ + chksum_val = g_compute_checksum_for_string(G_CHECKSUM_MD5,m+CHECKSUM_LENGTH,msize); + /*prefix checksum to the data */ + memcpy(m,chksum_val,CHECKSUM_LENGTH); + if ( NULL != r ) { + /*base64 encode for whole string checksum and data*/ + *r =(unsigned char*)g_base64_encode(m,msize+CHECKSUM_LENGTH); + if ( NULL != len ) *len = strlen((char*)*r); + } + free(m); + g_free(chksum_val);/*free checksum string */ + + return 0; +} + +int +bundle_free_encoded_rawdata(bundle_raw **r) +{ + if(!*r) return -1; /*TC_FIX - double free sigabrt handling */ + + free(*r); + *r=NULL; + return 0; +} + +bundle * +bundle_decode(const bundle_raw *r, const int data_size) +{ + bundle *b; + bundle_raw *p_r; + unsigned char *d_str; + unsigned int d_len_raw; + unsigned char *d_r; + unsigned int d_len; + char *extract_cksum; + gchar* compute_cksum; + + if(NULL == r) { + errno = EINVAL; + return NULL; + } + + extract_cksum = calloc(CHECKSUM_LENGTH+1, sizeof(char)); + if(unlikely(NULL== extract_cksum)) + { + errno = ENOMEM; + return NULL; + } + + /* base 64 decode of input string*/ + d_str = g_base64_decode((char*)r, &d_len_raw); + /*extract checksum from the received string */ + strncpy(extract_cksum,d_str,CHECKSUM_LENGTH); + /* compute checksum for the data */ + compute_cksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,d_str+CHECKSUM_LENGTH,d_len_raw-CHECKSUM_LENGTH); + /*compare checksum values- extracted from the received string and computed from the data */ + if(strcmp(extract_cksum,compute_cksum)!=0) + { + free(extract_cksum); + g_free(compute_cksum); + return NULL; + } + d_r = d_str+CHECKSUM_LENGTH; + d_len= d_len_raw-CHECKSUM_LENGTH; + + /* re-construct bundle */ + b = bundle_create(); + + p_r = (bundle_raw *)d_r; + + size_t bytes_read; + keyval_t *kv; + + while(p_r < d_r + d_len - 1) { + kv = NULL; // To get a new kv + + // Find type, and use decode function according to type + int type = keyval_get_type_from_encoded_byte(p_r); + + if(keyval_type_is_array(type)) { + bytes_read = keyval_array_decode(p_r, (keyval_array_t **) &kv); + } + else { + bytes_read = keyval_decode(p_r, &kv); + } + + if(kv) _bundle_append_kv(b, kv); + else { break; } + p_r += bytes_read; + } + + free(extract_cksum); + g_free(compute_cksum); + free(d_str); + + return b; +} + +struct _argv_idx { + int argc; + char **argv; + int idx; +}; + +int +bundle_encode_raw(bundle *b, bundle_raw **r, int *len) +{ + keyval_t *kv = NULL; + unsigned char *m = NULL; + unsigned char *p_m = NULL; + unsigned char *byte = NULL; + size_t byte_len; + gchar *chksum_val = NULL; + + if(NULL == b || NULL == r) { + errno = EINVAL; + return -1; + } + + /* calculate memory size */ + size_t msize = 0; // Sum of required size + + kv = b->kv_head; + while(kv != NULL) { + msize += kv->method->get_encoded_size(kv); + kv = kv->next; + } + m = calloc(msize+CHECKSUM_LENGTH, sizeof(unsigned char)); + if(unlikely(NULL == m )) { errno = ENOMEM; return -1; } + + p_m = m+CHECKSUM_LENGTH; /* temporary pointer */ + + kv = b->kv_head; + while(kv != NULL) { + byte = NULL; + byte_len = 0; + + kv->method->encode(kv, &byte, &byte_len); + memcpy(p_m, byte, byte_len); + + p_m += byte_len; + kv = kv->next; + + free(byte); + } + + /*compute checksum from the data*/ + chksum_val = g_compute_checksum_for_string(G_CHECKSUM_MD5,m+CHECKSUM_LENGTH,msize); + /*prefix checksum to the data */ + memcpy(m,chksum_val,CHECKSUM_LENGTH); + /*if ( NULL != r ) { + *r =(unsigned char*)g_base64_encode(m,msize+CHECKSUM_LENGTH); + if ( NULL != len ) *len = strlen((char*)*r); + } + free(m);*/ + *r = m; + *len = msize+CHECKSUM_LENGTH; + g_free(chksum_val);/*free checksum string */ + + return 0; +} + +bundle * +bundle_decode_raw(const bundle_raw *r, const int data_size) +{ + bundle *b = NULL; + bundle_raw *p_r = NULL; + unsigned char *d_str = NULL; + unsigned int d_len_raw; + unsigned char *d_r = NULL; + unsigned int d_len; + char *extract_cksum = NULL; + gchar* compute_cksum = NULL; + + if(NULL == r) { + errno = EINVAL; + return NULL; + } + + extract_cksum = calloc(CHECKSUM_LENGTH+1, sizeof(char)); + if(unlikely(NULL== extract_cksum)) + { + errno = ENOMEM; + return NULL; + } + + /* base 64 decode of input string*/ + //d_str = g_base64_decode((char*)r, &d_len_raw); + d_str = r; + d_len_raw = data_size; + /*extract checksum from the received string */ + strncpy(extract_cksum,d_str,CHECKSUM_LENGTH); + /* compute checksum for the data */ + compute_cksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,d_str+CHECKSUM_LENGTH,d_len_raw-CHECKSUM_LENGTH); + /*compare checksum values- extracted from the received string and computed from the data */ + if(strcmp(extract_cksum,compute_cksum)!=0) + { + free(extract_cksum); + g_free(compute_cksum); + return NULL; + } + d_r = d_str+CHECKSUM_LENGTH; + d_len= d_len_raw-CHECKSUM_LENGTH; + + /* re-construct bundle */ + b = bundle_create(); + + p_r = (bundle_raw *)d_r; + + size_t bytes_read; + keyval_t *kv; + + while(p_r < d_r + d_len - 1) { + kv = NULL; // To get a new kv + + // Find type, and use decode function according to type + int type = keyval_get_type_from_encoded_byte(p_r); + + if(keyval_type_is_array(type)) { + bytes_read = keyval_array_decode(p_r, (keyval_array_t **) &kv); + } + else { + bytes_read = keyval_decode(p_r, &kv); + } + + if(kv) _bundle_append_kv(b, kv); + else { break; } + p_r += bytes_read; + } + + free(extract_cksum); + g_free(compute_cksum); + //free(d_str); + + return b; +} + + +void +_iter_export_to_argv(const char *key, const int type, const keyval_t *kv, void *user_data) +{ + struct _argv_idx *vi = (struct _argv_idx *)user_data; + + vi->argv[vi->idx] = (char *)key; + + unsigned char *byte = NULL, *encoded_byte = NULL; + size_t byte_len = 0; + + if(0 == kv->method->encode((struct keyval_t *)kv, &byte, &byte_len)) { + // TODO: encode FAILED! + BUNDLE_EXCEPTION_PRINT("bundle: FAILED to encode keyval: %s\n", key); + return; + } + // bas64 encode + + encoded_byte =(unsigned char *) g_base64_encode(byte, byte_len); + if(NULL == encoded_byte) { + BUNDLE_EXCEPTION_PRINT("bundle: failed to encode byte\n"); + return; + } + + vi->argv[vi->idx + 1] =(char*)encoded_byte; + (vi->idx) += 2; + + free(byte); +} + +int +bundle_export_to_argv(bundle *b, char ***argv) +{ + int argc, item_count; + + item_count = bundle_get_count(b); + argc = 2 * item_count + 2; /* 2 more count for argv[0] and arv[1] = encoded */ + *argv = calloc(argc + 1, sizeof(char *)); + if(!*argv) return -1; + + struct _argv_idx vi; + vi.argc = argc; + vi.argv = *argv; + vi.idx = 2; /* start from index 2*/ + vi.argv[1]=TAG_IMPORT_EXPORT_CHECK; /* set argv[1] as encoded*/ + /*BUNDLE_LOG_PRINT("\nargument 1 is %s",vi.argv[1]);*/ + + bundle_foreach(b, _iter_export_to_argv, &vi); + + return argc; +} + +int bundle_free_exported_argv(int argc, char ***argv) +{ + if(!*argv) return -1; /*TC_FIX : fix for double free- sigabrt */ + + int i; + for(i=1; i < argc; i+=2) { + free((*argv)[i+1]); + } + + free(*argv); + *argv= NULL; + return 0; +} + + bundle * +bundle_import_from_argv(int argc, char **argv) +{ + if(!argv) return NULL; /* TC_FIX error handling for argv =NULL*/ + + bundle *b = bundle_create(); + if(!b) return NULL; + + + /* + int i; + for(i=0; itype; + else { + errno = ENOKEY; + return BUNDLE_TYPE_NONE; + } +} + +// array functions +/** Get length of an array + */ + unsigned int +bundle_get_array_len(bundle *b, const char *key) +{ + return 0; +} + +/** Get size of an item in byte, of given pointer + */ + size_t +bundle_get_array_val_size(bundle *b, const char *key, const void *val_ptr) +{ + return 0; +} +static int +bundle_set_array_val(bundle *b, const char *key, const int type, const unsigned int idx, const void *val, const size_t size) +{ +//void **array = NULL; + + keyval_t *kv = _bundle_find_kv(b, key); + if(NULL == kv) return -1; + + if(type != kv->type) { + errno = EINVAL; + return -1; + } + + if(! keyval_type_is_array(kv->type)) { // TODO: Is this needed? + errno = EINVAL; + return -1; + } + + keyval_array_t *kva = (keyval_array_t *)kv; + + if(! keyval_array_is_idx_valid(kva, idx)) { + errno = EINVAL; + return -1; + } + + if(!kva->array_val) { // NULL value test (TODO: is this needed?) + errno = ENOMEM; + return -1; + } + + return keyval_array_set_element(kva, idx, val, size); +} + + + int +bundle_add_str_array(bundle *b, const char *key, const char **str_array, const int len) +{ + return _bundle_add_kv(b, key, str_array, 0, BUNDLE_TYPE_STR_ARRAY, len); +} + + + int +bundle_get_val_array(bundle *b, const char *key, char ***str_array, int *len) +{ + return _bundle_get_val(b, key, BUNDLE_TYPE_STR_ARRAY, (void **) str_array, NULL,(unsigned int *)len, NULL); +} + +const char ** bundle_get_str_array(bundle *b, const char *key,int *len) +{ + const char **arr_val = NULL; + int r = 0; + + r = bundle_get_val_array(b,key,(char***)&arr_val,len); + return arr_val; + +} + + + int +bundle_compare(bundle *b1, bundle *b2) +{ + if(!b1 || !b2) return -1; + + keyval_t *kv1, *kv2; + //keyval_array_t *kva1, *kva2; + //char *key; + + if(bundle_get_count(b1) != bundle_get_count(b2)) return 1; + for(kv1 = b1->kv_head; kv1 != NULL; kv1 = kv1->next) { + kv2 = _bundle_find_kv(b2, kv1->key); + if(!kv2) return 1; + if(kv1->method->compare(kv1, kv2)) return 1; + } + return 0; +} + + + + int +bundle_set_str_array_element(bundle *b, const char *key, const unsigned int idx, const char *val) +{ + if(!val) { + errno = EINVAL; + return -1; + } + return bundle_set_array_val(b, key, BUNDLE_TYPE_STR_ARRAY, idx, val, strlen(val)+1); +} + + +// byte type + int +bundle_add_byte(bundle *b, const char *key, const void *byte, const size_t size) +{ + return _bundle_add_kv(b, key, byte, size, BUNDLE_TYPE_BYTE, 1); +} + + int +bundle_get_byte(bundle *b, const char *key, void **byte, size_t *size) +{ + return _bundle_get_val(b, key, BUNDLE_TYPE_BYTE, (void **) byte, size, NULL, NULL); +} + + int +bundle_add_byte_array(bundle *b, const char *key, void **byte_array, const unsigned int len) +{ + return _bundle_add_kv(b, key, byte_array, 0, BUNDLE_TYPE_BYTE_ARRAY, len); +} + + int +bundle_get_byte_array(bundle *b, const char *key, void ***byte_array, unsigned int *len, unsigned int **array_element_size) +{ + return _bundle_get_val(b, key, BUNDLE_TYPE_BYTE_ARRAY, (void **)byte_array, NULL, len, array_element_size); +} + + + int +bundle_set_byte_array_element(bundle *b, const char *key, const unsigned int idx, const void *val, const size_t size) +{ + return bundle_set_array_val(b, key, BUNDLE_TYPE_BYTE_ARRAY, idx, val, size); +} + diff --git a/src/keyval.c b/src/keyval.c new file mode 100755 index 0000000..5397f90 --- /dev/null +++ b/src/keyval.c @@ -0,0 +1,248 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + +/** + * keyval.c + * Implementation of keyval object + */ + +#include "keyval_type.h" +#include "keyval.h" +#include "bundle_log.h" +#include +#include +extern int errno; + +static keyval_method_collection_t method = { + keyval_free, + keyval_compare, + keyval_get_encoded_size, + keyval_encode, + keyval_decode +}; + +keyval_t * +keyval_new(keyval_t *kv, const char *key, const int type, const void *val, const size_t size) +{ + int must_free_obj; + must_free_obj = kv ? 0 : 1; + + if(!kv) { + kv = calloc(1, sizeof(keyval_t)); + if(!kv) { + //errno = ENOMEM; // set by calloc + return NULL; + } + } + + // key + if(kv->key) { + keyval_free(kv, must_free_obj); + return NULL; + } + kv->key = strdup(key); + if(!kv->key) { + //errno = ENOMEM; // set by strdup + keyval_free(kv, must_free_obj); + return NULL; + } + + // elementa of primitive types + kv->type = type; + kv->size = size; + + if(size) { + kv->val = calloc(1, size); // allocate memory unconditionally ! + if(!kv->val) { + errno = ENOMEM; + keyval_free(kv, 1); + return NULL; + } + if(val) { + memcpy(kv->val, val, size); + } + } + + // Set methods + kv->method = &method; + + return kv; +} + +void +keyval_free(keyval_t *kv, int do_free_object) +{ + //int i; + + if(NULL == kv) return; + + if(kv->key) { + free(kv->key); + kv->key = NULL; + } + + if(NULL != kv->val) { + free(kv->val); + kv->val = NULL; + } + + if(do_free_object) free(kv); + + return; +} + +int +keyval_get_data(keyval_t *kv, int *type, void **val, size_t *size) +{ + if(!kv) return -EINVAL; + if(keyval_type_is_array(kv->type)) return -EINVAL; + + if(type) *type = kv->type; + if(val) *val = kv->val; + if(size) *size = kv->size; + + return 0; +} + +int +keyval_compare(keyval_t *kv1, keyval_t *kv2) +{ + if(!kv1 || !kv2) return -1; + + if(0 != strcmp(kv1->key, kv2->key)) return 1; + if(kv1->type != kv2->type) return 1; + if(kv1->size != kv2->size) return 1; + + if(kv1->val == NULL && kv2->val == NULL) return 0; + if(kv1->val == NULL || kv2->val == NULL) return 1; + if(0 != memcmp(kv1->val, kv2->val, kv1->size)) return 1; + + return 0; +} + +size_t +keyval_get_encoded_size(keyval_t *kv) +{ + if(!kv) return 0; + + size_t encoded_size + = sizeof(size_t) // total size + + sizeof(int) // type + + sizeof(size_t) // key size + + strlen(kv->key) + 1 // key (+ null byte) + + sizeof(size_t) // size + + kv->size; // val + + return encoded_size; +} + +/** + * encode a keyval to byte + * + * @pre kv must be valid. + * @post byte must be freed. + * @param[in] kv + * @param[out] byte + * @param[out] byte_len + * @return byte_len + */ +size_t +keyval_encode(keyval_t *kv, unsigned char **byte, size_t *byte_len) +{ + /* + * type + * key size + * key + * val size + * val + */ + + static const size_t sz_type = sizeof(int); + static const size_t sz_keysize = sizeof(size_t); + size_t sz_key = strlen(kv->key) + 1; + static const size_t sz_size = sizeof(size_t); + size_t sz_val = kv->size; + + *byte_len = keyval_get_encoded_size(kv); + + *byte = calloc(1, *byte_len); + if(!*byte) return 0; + + unsigned char *p = *byte; + + memcpy(p, byte_len, sizeof(size_t)); p += sizeof(size_t); + memcpy(p, &(kv->type), sz_type); p += sz_type; + memcpy(p, &sz_key, sz_keysize); p += sz_keysize; + memcpy(p, kv->key, sz_key); p += sz_key; + memcpy(p, &(kv->size), sz_size); p += sz_size; + memcpy(p, kv->val, sz_val); p += sz_val; + + return *byte_len; +} + +/** + * decode a byte stream to a keyval + * + * @param[in] byte byte stream. + * @param[in|out] kv keyval. + * If kv is NULL, new keyval_t object comes. + * If kv is not NULL, given kv is used. (No new kv is created.) + * @return Number of bytes read from byte. + */ +size_t +keyval_decode(unsigned char *byte, keyval_t **kv) +{ + static const size_t sz_byte_len = sizeof(size_t); + static const size_t sz_type = sizeof(int); + static const size_t sz_keysize = sizeof(size_t); + static const size_t sz_size = sizeof(size_t); + + unsigned char *p = byte; + + size_t byte_len = *((size_t *)p); p += sz_byte_len; + int type = *((int *)p); p += sz_type; + size_t keysize = *((size_t *)p); p += sz_keysize; + char *key = (char *)p; p += keysize; + size_t size = *((size_t *)p); p += sz_size; + void *val = (void *)p; p += size; + + if(kv) *kv = keyval_new(*kv, key, type, val, size); // If *kv != NULL, use given kv + + return byte_len; +} + + +int +keyval_get_type_from_encoded_byte(unsigned char *byte) +{ + // skip total size (== sizeof(size_t)) + static const size_t sz_byte_len = sizeof(size_t); + + unsigned char *p=byte; + p += sz_byte_len; + int type = *((int *)p); + return type; + + //return (int )*(byte + sizeof(size_t)); +} + diff --git a/src/keyval_array.c b/src/keyval_array.c new file mode 100755 index 0000000..af2aa12 --- /dev/null +++ b/src/keyval_array.c @@ -0,0 +1,337 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + +/** + * keyval_array.c + * Implementation of keyval_array object + */ + +#include "keyval_array.h" +#include "keyval.h" +#include "keyval_type.h" +#include "bundle.h" +#include "bundle_log.h" + +#include +#include +#include + + +static keyval_method_collection_t method = { + (keyval_method_free_t) keyval_array_free, + (keyval_method_compare_t) keyval_array_compare, + (keyval_method_get_encoded_size_t) keyval_array_get_encoded_size, + (keyval_method_encode_t) keyval_array_encode, + (keyval_method_decode_t) keyval_array_decode +}; + +keyval_array_t * +keyval_array_new(keyval_array_t *kva, const char *key, const int type, const void **array_val, const unsigned int len) +{ + int must_free_obj; + must_free_obj = kva ? 0 : 1; + + if(!kva) { + kva = calloc(1, sizeof(keyval_array_t)); + if(unlikely(NULL==kva)) { + errno = ENOMEM; + return NULL; + } + } + + // keyval setting + keyval_t *kv = keyval_new((keyval_t *)kva, key, type, NULL, 0); + if(unlikely(NULL==kv)) + { + errno = ENOMEM; + return NULL; + } + + kv->type = kv->type | BUNDLE_TYPE_ARRAY; + + kva->len = len; + + // Set array value, if exist + if(kva->array_val) { + errno=EINVAL; + if(must_free_obj) keyval_array_free(kva, 1); + return NULL; + } + kva->array_val = calloc(len, sizeof(void *)); + if(!(kva->array_val)) { + errno = ENOMEM; + keyval_array_free(kva, 1); + return NULL; + } + // array_element_size + kva->array_element_size = calloc(len, sizeof(size_t)); + if(!(kva->array_element_size)) { + errno = ENOMEM; + keyval_array_free(kva, 1); + return NULL; + } + // If avaliable, copy array val + if(array_val + && keyval_type_is_measurable(type) + && keyval_type_get_measure_size_func(type)) { + // array_val have original data array. copy it! + + if(keyval_array_copy_array((keyval_array_t*)kv, + (void**)array_val, + len, + keyval_type_get_measure_size_func(type)) + ) { + keyval_array_free(kva, 1); + return NULL; + } + } + + // Set methods + kv->method = &method; + + return kva; +} + +void +keyval_array_free(keyval_array_t *kva, int do_free_object) +{ + if(!kva) return; + + // free keyval_array elements + free(kva->array_element_size); + int i; + for(i=0; ilen; i++) { + if(kva->array_val[i]) free(kva->array_val[i]); + } + free(kva->array_val); + + // free parent + keyval_free((keyval_t *)kva, 0); + + // free object + if(do_free_object) free(kva); +} + +int +keyval_array_compare(keyval_array_t *kva1, keyval_array_t *kva2) +{ + keyval_t *kv1, *kv2; + if(!kva1 || !kva2) return -1; + + kv1 = (keyval_t *)kva1; + kv2 = (keyval_t *)kva2; + + if(0 != strcmp(kv1->key, kv2->key)) return 1; + if(kv1->type != kv2->type) return 1; + if(kva1->len != kva2->len) return 1; + int i; + for(i=0; ilen; i++) { + if(kva1->array_val[i] == NULL && kva2->array_val[i] == NULL) continue; + if(kva1->array_val[i] == NULL || kva2->array_val[i] == NULL) return 1; + if(0 != memcmp(kva1->array_val[i], kva2->array_val[i], kva1->array_element_size[i])) return 1; + } + + return 0; +} + +int +keyval_array_copy_array(keyval_array_t *kva, void **array_val, unsigned int array_len, size_t (*measure_val_len)(void * val)) +{ + keyval_t *kv = (keyval_t *)kva; + + // Get measure_size function of the value type + keyval_type_measure_size_func_t measure_size = keyval_type_get_measure_size_func(kv->type); + if(!measure_size) return -1; + + // Copy each array item + int i; + for(i=0; i < array_len; i++) { + kva->array_val[i] = malloc(measure_size(array_val[i])); + if(!(kva->array_val[i])) { + errno = ENOMEM; + goto cleanup_exit; + } + memcpy(kva->array_val[i], array_val[i], measure_size(array_val[i])); + kva->array_element_size[i] = measure_size(array_val[i]); + } + return 0; + +cleanup_exit: + for(i=0; iarray_val[i]) { + free(kva->array_val[i]); + kva->array_val[i] = NULL; + } + } + return -1; +} + +int +keyval_array_is_idx_valid(keyval_array_t *kva, int idx) +{ + //keyval_t *kv = (keyval_t *)kva; + if(kva && kva->len > idx && 0 <= idx) return 1; + return 0; +} + +int +keyval_array_set_element(keyval_array_t *kva, int idx, void *val, size_t size) +{ + if(kva->array_val[idx]) { // An element is already exist in the idx! + if(!val) { // val==NULL means 'Free this element!' + free(kva->array_val[idx]); + kva->array_val[idx] = NULL; + kva->array_element_size[idx] = 0; + } + else { + // Error case! + errno = EINVAL; + return -1; + } + } + else { + // Normal case. Copy value into the array. + kva->array_val[idx] = malloc(size); + if(!(kva->array_val[idx])) { + errno = ENOMEM; + return -1; + } + if(val) { + memcpy(kva->array_val[idx], val, size); // val + kva->array_element_size[idx] = size; // size + } + } + + return 0; +} + +int +keyval_array_get_data(keyval_array_t *kva, int *type, + void ***array_val, unsigned int *len, size_t **array_element_size) +{ + if(!kva) return -EINVAL; + keyval_t *kv = (keyval_t *)kva; + if(!keyval_type_is_array(kv->type)) return -EINVAL; + + // Return values + if(type) *type = kv->type; + if(array_val) *array_val = kva->array_val; + if(len) *len = kva->len; + if(array_element_size) *array_element_size = kva->array_element_size; + + return 0; +} + +size_t +keyval_array_get_encoded_size(keyval_array_t *kva) +{ + size_t sum_array_element_size = 0; + int i; + for(i=0; i < kva->len; i++) { + sum_array_element_size += kva->array_element_size[i]; + } + size_t encoded_size + = sizeof(size_t) // total size + + sizeof(int) // type + + sizeof(size_t) // keysize + + strlen(((keyval_t *)kva)->key) + 1 // key (+ null byte) + + sizeof(int) // len + + kva->len * sizeof(size_t) // array_element_size + + sum_array_element_size; + + return encoded_size; +} + +size_t +keyval_array_encode(keyval_array_t *kva, void **byte, size_t *byte_len) +{ + keyval_t *kv = (keyval_t *)kva; + int i; + + // Calculate memory size for kva + static const size_t sz_type = sizeof(int); + static const size_t sz_keysize = sizeof(size_t); + size_t sz_key = strlen(kv->key) + 1; + static const unsigned int sz_len = sizeof(int); + size_t sz_array_element_size = kva->len * sizeof(size_t); + size_t sz_array_val = 0; + for(i=0; i < kva->len; i++) { + sz_array_val += kva->array_element_size[i]; + } + + // Allocate memory + *byte_len = keyval_array_get_encoded_size(kva); + *byte = calloc(1, *byte_len); + if(!*byte) return 0; + + // Copy data + unsigned char *p = *byte; + + memcpy(p, byte_len, sizeof(size_t)); p += sizeof(size_t); + memcpy(p, &(kv->type), sz_type); p += sz_type; + memcpy(p, &sz_key, sz_keysize); p += sz_keysize; + memcpy(p, kv->key, sz_key); p += sz_key; + memcpy(p, &(kva->len), sz_len); p += sz_len; + memcpy(p, kva->array_element_size, sz_array_element_size); p += sz_array_element_size; + for(i=0; i < kva->len; i++) { + memcpy(p, kva->array_val[i], kva->array_element_size[i]); + p += kva->array_element_size[i]; + } + + return *byte_len; +} + +size_t +keyval_array_decode(void *byte, keyval_array_t **kva) +{ + static const size_t sz_byte_len = sizeof(size_t); + static const size_t sz_type = sizeof(int); + static const size_t sz_keysize = sizeof(size_t); + static const int sz_len = sizeof(unsigned int); + + unsigned char *p = byte; + + // Get data + size_t byte_len = *((size_t *)p); p += sz_byte_len; + int type = *((int *)p); p += sz_type; + size_t keysize = *((size_t *)p); p += sz_keysize; + char *key = (char *)p; p += keysize; + unsigned int len = *((unsigned int *)p); p += sz_len; + size_t *array_element_size = (size_t *) p; p += sizeof(size_t) * len; + void *array_val = (void *)p; + + *kva = keyval_array_new(NULL, key, type, NULL, len); + int i; + size_t elem_size = 0; + for(i=0; i < len; i++) { + elem_size += i ? array_element_size[i-1] : 0; + if(keyval_array_set_element(*kva, i, (void *)(array_val+elem_size), array_element_size[i])) { + keyval_array_free(*kva, 1); + *kva = NULL; + return 0; + } + } + + return byte_len; +} + diff --git a/src/keyval_type.c b/src/keyval_type.c new file mode 100755 index 0000000..0f69eee --- /dev/null +++ b/src/keyval_type.c @@ -0,0 +1,73 @@ +/* + * bundle + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jayoun Lee , Sewook Park , + * Jaeho Lee + * + * Licensed 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. + * + */ + + +#include "keyval_type.h" +#include "bundle_log.h" +#include + +void +keyval_type_init(void) +{ + static int is_done = 0; + + if(is_done) return; + + // Still do nothing + is_done = 1; +} + +int +keyval_type_is_array(int type) +{ + if(type & BUNDLE_TYPE_ARRAY) return 1; + return 0; +} + +int +keyval_type_is_measurable(int type) +{ + if(type & BUNDLE_TYPE_MEASURABLE) return 1; + return 0; +} + +keyval_type_measure_size_func_t +keyval_type_get_measure_size_func(int type) +{ + switch(type) { + case BUNDLE_TYPE_STR: + case BUNDLE_TYPE_STR_ARRAY: + return keyval_type_measure_size_str; + break; + default: + return NULL; + } + return NULL; +} + +size_t +keyval_type_measure_size_str(void *val) +{ + if(!val) return 0; + return strlen((char *)val) + 1; +} + diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..a35b79d --- /dev/null +++ b/test.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +cd `dirname $0` + +rm -rf cmake_tmp +mkdir cmake_tmp +cd cmake_tmp + +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd` +CFLAGS="-g $CFLAGS" LDFLAGS="-Wl,--as-needed -Wl,--hash-style=both" cmake .. -DCMAKE_INSTALL_PREFIX=/usr && make test && echo "Test OK. No error." + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100755 index 0000000..9126b44 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(test_bundle EXCLUDE_FROM_ALL + test_bundle.c + ) +target_link_libraries(test_bundle bundle) + +add_custom_target(test + COMMAND LD_LIBRARY_PATH=${CMAKE_BINARY_DIR} ./test_bundle + DEPENDS test_bundle + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + COMMENT "Run 'make test'" + ) diff --git a/test/Makefile b/test/Makefile new file mode 100755 index 0000000..f461477 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,10 @@ +#Steps to build the TC_bundle.c +#1.build the bundle code +#2.make +#3. TC_bundle binary file would be created. +export PKG_CONFIG_PATH=../debian/libbundle-dev/usr/lib/pkgconfig/ + +all: + sbs -e gcc -Wall -o TC_bundle TC_bundle.c `pkg-config --libs bundle` +clean: + rm -rf *.exe diff --git a/test/TC_bundle.c b/test/TC_bundle.c new file mode 100755 index 0000000..03e0c26 --- /dev/null +++ b/test/TC_bundle.c @@ -0,0 +1,1478 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define SUCCESS 1 +#define FAIL 0 +int ret_bundle_foreach=FAIL; +int ret_bundle_foreach_invalid=FAIL; +int ret_bundle_keyval_typeget=FAIL; +int ret_bundle_exp_imp_p=FAIL; +int ret_bundle_en_dec_p=FAIL; +int ret_exp_imp_cases=FAIL; +int ret_bundle_exp_invalid=FAIL; +int ret_bundle_imp_invalid=FAIL; +int ret_bundle_add=FAIL; +int ret_bundle_get_val=FAIL; +int ret_bundle_dup=FAIL; +int ret_bundle_encode=FAIL; +int ret_bundle_decode=FAIL; +int ret_bundle_free_encoded=FAIL; +int ret_bundle_get_type=FAIL; +int ret_tc_free_exp_argv=FAIL; +int ret_keyval_is_array=FAIL; +int ret_keyval_get_basicval=FAIL; +int ret_bundle_del=FAIL; +int ret_keyval_get_arrval=FAIL; +int ret_bundle_get_str_arr=FAIL; +int ret_bundle_add_str_arr=FAIL; + +void iterate_bundleforeach(const char *key,const int type, bundle_keyval_t *kv, void *data) +{ + switch(type) + { + case BUNDLE_TYPE_STR: + { + //printf("\n CASE: BUNDLE_TYPE_STR "); + char *basic_val=NULL; + size_t size; + bundle_keyval_get_basic_val(kv,(void *)&basic_val,&size); + //printf("Key: %s ---- Val: %s\n",key,basic_val); + break; + } + case BUNDLE_TYPE_STR_ARRAY: + { + //printf("\n CASE: BUNDLE_TYPE_STR_ARRAY: "); + void **arr=NULL; + size_t *array_ele_size=NULL; + unsigned int ele_nos=0; + int i=0; + bundle_keyval_get_array_val(kv,&arr,&ele_nos,&array_ele_size); + //printf("Total Elements: %d\n",ele_nos); + //printf("Key: %s \n",key); + for(i=0;i, user_data=0xbead0a24)*/ + argc1=bundle_export_to_argv(b_null,&argv1); + return SUCCESS; + +} +int TC_bundle_import_from_argv_invalid() +{ + //printf("\n ====================================================================\n"); + //printf("\nTESTCASE: TC_bundle_import_from_argv_invalid "); + bundle *b_new=NULL; + int argc1=0; + char **argv1=NULL; + + +/* INVALID: passing invalid arguments -not exported/encoded */ +/*CASE1: argc1=0 */ + argc1=0; + argv1 = calloc(argc1+1,sizeof(char*)); + b_new=bundle_import_from_argv(argc1,argv1); + assert(NULL != b_new); + assert(0 == bundle_get_count(b_new)); + bundle_foreach(b_new,(void *)iterate_bundleforeach,NULL); + assert(0==bundle_free(b_new)); + +/*CASE2: argv1 =NULL--FIXED : segmentation fault-put check in code*/ + argc1=2; + argv1=NULL; + b_new=bundle_import_from_argv(argc1,argv1); + //printf("\n cannot form bundle"); + assert(NULL == b_new); +/*CASE3: argc1=4 /argv1!=NULL but all arguments value= null */ + argc1=4; +// argv1=calloc(1,sizeof(char*)); //sigsegv - atleast no of elements= arc1 should be allocated memory properly. + argv1=calloc(5,sizeof(char*)); + b_new=bundle_import_from_argv(argc1,argv1); + assert(NULL != b_new); + assert(0 == bundle_get_count(b_new)); + assert(0==bundle_free(b_new)); +/*CASE5: passing even no of arguments-[max=4] 6 arguments passed-no of bundle elements must be 2.*/ + argc1=4; + argv1=NULL; + argv1=calloc(5,sizeof(char*)); + argv1[0]="prog_name"; + argv1[1]="k2"; + argv1[2]="v2"; + argv1[3]="k3"; + argv1[4]="v3"; + argv1[5]="k4";//add extra- should not get added to bundle + argv1[6]="v4";//add extra- should not get added to bundle + b_new=bundle_import_from_argv(argc1,argv1); + assert(NULL != b_new); + //printf("\n no of elements in imported bundle is%d", bundle_get_count(b_new)); + assert(2 == bundle_get_count(b_new)); + bundle_foreach(b_new,(void *)iterate_bundleforeach,NULL); + assert(0==bundle_free(b_new)); +/*CASE6: passing odd no of arguments- [max=4]3 arguments passed-no of bundle elements will be 1.*/ + argc1=4; + argv1= NULL; + argv1=calloc(5,sizeof(char*)); + argv1[0]="prog_name"; + argv1[1]="k4"; + argv1[2]="v4"; + argv1[3]="k5"; + b_new=bundle_import_from_argv(argc1,argv1); + assert(NULL != b_new); + //printf("\n no of elements in imported bundle is%d", bundle_get_count(b_new)); + //bundle_foreach(b_new,(void *)iterate_bundleforeach,NULL); + assert(1 == bundle_get_count(b_new)); + assert(0==bundle_free(b_new)); + return SUCCESS; +} +int TC_bundle_export_import_cases() +{ + //printf("\n ====================================================================\n"); + //printf("\nTESTCASE: TC_bundle_export_import_cases "); + bundle *b=NULL; + bundle *b_new=NULL; + int argc1=0; + char **argv1=NULL; + + b=bundle_create(); + assert(NULL != b); + + +/*CASE1:bundle created succesfully- no keyval pair added ||return value of bundle_export_to_argv() >=2 in success and -1 in failure. */ + argc1=bundle_export_to_argv(b,&argv1); + //printf("\nargc is %d",argc1); + assert(argc1>0); + + b_new=bundle_import_from_argv(argc1,argv1); + assert(NULL != b_new); + assert(0 == bundle_get_count(b_new)); + /*reset values*/ + assert(0==bundle_free(b_new)); + argc1=0; + argv1=NULL; + +/*CASE2: adding elements to bundle and then export-import*/ + assert(0 == bundle_add(b, "k1", "val1")); + assert(0 == bundle_add(b, "k2", "val2")); + assert(0 == bundle_add(b, "k3", "val3")); + + argc1=bundle_export_to_argv(b,&argv1); + //printf("\nargc is %d",argc1); + assert(argc1>0); + assert(argc1==8); /*argc1 = 2*no of bundle elements +2 = actual count of argv [last null terminator not counted in argc1]*/ + assert(argv1!=NULL); + assert(argv1[0]==NULL); + assert(argv1[argc1]==NULL);/*last element must be NULL */ + + b_new=bundle_import_from_argv(argc1,argv1); + assert(NULL != b_new); + assert(3 == bundle_get_count(b_new)); + assert(0== strcmp(bundle_get_val(b_new,"k1"),bundle_get_val(b,"k1"))); + assert(0== strcmp(bundle_get_val(b_new,"k2"),bundle_get_val(b,"k2"))); + assert(0== strcmp(bundle_get_val(b_new,"k3"),bundle_get_val(b,"k3"))); + bundle_foreach(b_new,(void *)iterate_bundleforeach,NULL); + + + assert(0==bundle_free(b_new)); + assert(0==bundle_free(b)); + return SUCCESS; + +} +int TC_bundle_add() +{ + //printf("\n ====================================================================\n"); + //printf("\n TESTCASE : TC_bundle_add"); + bundle *b=NULL; + b=bundle_create(); + assert(NULL != b); + + bundle *b2=NULL; + + assert(0 == bundle_add(b, "key1", "val1")); + assert(0 == bundle_add(b, "key2", "val2")); +/*duplicate key */ + assert(0 != bundle_add(b, "key1", "val123")); + //printf("\n 1 %s",strerror(errno)); + assert(EPERM == errno ); +/*Null key */ + assert(0 != bundle_add(b, NULL, "val123")); + //printf("\n 2 %s",strerror(errno)); + assert(EKEYREJECTED == errno ); +/*Empty(string) key */ + assert(0 != bundle_add(b,"","val123")); + //printf("\n 2-empty key %s",strerror(errno)); + assert(EKEYREJECTED == errno ); +/*Null value */ + assert(0 != bundle_add(b, "key3", NULL)); + //printf("\n 3 %s",strerror(errno)); + assert(EINVAL == errno ); +/*Null bundle */ + assert(0 != bundle_add(NULL,"key4", "val123")); + //printf("\n 4 %s",strerror(errno)); + assert(EINVAL == errno ); +/*Null bundle/value - duplicate key */ + assert(0 != bundle_add(NULL,"key4", NULL)); + //printf("\n 5 %s",strerror(errno)); + assert(EINVAL == errno ); +/*Null value - duplicate key */ + assert(0 != bundle_add(b,"key4", NULL)); + //printf("\n 6 %s",strerror(errno)); + assert(EINVAL == errno ); +/*get value for given key */ + assert(0==strcmp("val1",bundle_get_val(b,"key1"))); + assert(0==strcmp("val2",bundle_get_val(b,"key2"))); +/*get count*/ + assert(2==bundle_get_count(b)); +/* add one more key-val */ + assert(0 == bundle_add(b, "k3", "v3")); +/*get count again - should be incremented*/ + assert(3 == bundle_get_count(b)); +/*add same key-val to different bundle- b2 */ + + b2=bundle_create(); + assert(NULL != b2); + assert(0 == bundle_add(b2, "key1", "val1")); + assert(0 == bundle_add(b2, "key2", "v2")); + assert(0==strcmp("v2",bundle_get_val(b2,"key2"))); + assert(2==bundle_get_count(b2)); +/*Empty(string) value- allowed */ + assert(0 == bundle_add(b2,"key3","")); +/*Bundle_add without prior bundle_create */ + bundle *b3=NULL; + assert(0 != bundle_add(b3, "k1", "v1")); + assert(EINVAL == errno ); + return SUCCESS; +} +int TC_bundle_get_val() +{ + //printf("\n ====================================================================\n"); + //printf("\n TEST CASE :TC_bundle_get_val"); + bundle *b=NULL; + bundle *b1=NULL; + b=bundle_create(); + assert(NULL != b); + assert(0 == bundle_add(b, "key1", "val1")); + assert(0 == bundle_add(b, "key2", "val2")); + + assert(0==strcmp("val1",bundle_get_val(b,"key1"))); + assert(0==strcmp("val2",bundle_get_val(b,"key2"))); +/*wrong key passed as input */ + assert(NULL==bundle_get_val(b,"key4")); + assert(ENOKEY == errno ); +/*bundle = NULL */ + assert(NULL==bundle_get_val(NULL,"key4")); + assert(EINVAL == errno ); +/*bundle = not created */ + assert(NULL==bundle_get_val(b1,"key4")); + assert(EINVAL == errno ); +/*key = NULL, bundle = proper */ + assert(NULL==bundle_get_val(b,NULL)); + assert(EKEYREJECTED == errno ); +/*pass string instead of bundle -sigsegv */ +// assert(NULL==bundle_get_val("bundle","key1")); +// assert(EINVAL == errno ); + + assert(0==bundle_free(b)); + return SUCCESS; + +} +#if 0 +int TC_bundle_add_byte() +{ +/*pass str="aa" instead of byte="aa\0"*/ + //printf("\n ====================================================================\n"); + //printf("\n TESTCASE: TC_bundle_add_byte"); + bundle *b=NULL; + bundle *b1=NULL; + b=bundle_create(); + assert(NULL != b); +/*valid cases */ + char *data_1byte ="bbbbb"; + char *data_2byte ="aaaa"; + assert(0 == bundle_add_byte(b, "k4", (void *)data_1byte, strlen(data_1byte)+1)); + assert(0==bundle_add_byte(b, "k5", (void *)data_2byte, strlen(data_2byte)+1)); +/*duplicate value */ + assert(0==bundle_add_byte(b, "k7", (void *)data_2byte, strlen(data_2byte)+1)); +/*value and size NULL */ + assert(0==bundle_add_byte(b, "k8",NULL,NULL)); +/*value = NULL, size not NULL */ + assert(0==bundle_add_byte(b, "k9",NULL,9)); + +/*invalid cases */ +/*bundle = NULL */ + assert(0!=bundle_add_byte(b1, "k5", (void *)data_2byte,(size_t)strlen(data_2byte)+1)); + assert(EINVAL == errno ); +/*duplicate key */ + assert(0!=bundle_add_byte(b, "k5","abcd",4)); + assert(EPERM == errno); +/*empty key */ + assert(0!=bundle_add_byte(b,"","lion",4)); + assert(EKEYREJECTED == errno ); + assert(0==bundle_free(b)); + return SUCCESS; +} +#endif +////// +int TC_bundle_add_str_array() +{ + //printf("\n ====================================================================\n"); + //printf("\n TESTCASE :TC_bundle_add_str_array"); + const char *arr[]={"v1","v2","v3","v4"}; + bundle *b=NULL; + bundle *b1=NULL; + b=bundle_create(); + assert(NULL != b); + + assert(0==bundle_add_str_array(b,"k1",&arr,4)); + + +/*bundle= NULL - fail */ + assert(0!=bundle_add_str_array(b1,"key1",NULL,6)); + assert(EINVAL == errno ); +/*duplicate key - fail */ + assert(0!=bundle_add_str_array(b,"k1",NULL,6)); + assert(EPERM == errno ); +/*empty key - fail */ + assert(0!=bundle_add_str_array(b,"",NULL,6)); + assert(EKEYREJECTED == errno ); +/*No of elements = NULL - success */ + assert(0==bundle_add_str_array(b,"k3",NULL,NULL)); +/*add new array with a different key and 6 elements -success */ + assert(0==bundle_add_str_array(b,"k4",NULL,6)); + + assert(0==bundle_free(b)); + return SUCCESS; +} +/////// +#if 0 +int TC_bundle_add_byte_array() +{ + //printf("\n ====================================================================\n"); + //printf("\n TESTCASE :TC_bundle_add_byte_array"); + bundle *b=NULL; + bundle *b1=NULL; + b=bundle_create(); + assert(NULL != b); +/* cases */ + assert(0==bundle_add_byte_array(b,"k1",NULL,4)); + assert(0==bundle_set_byte_array_element(b,"k1",0,"ccc\0",4)); + assert(0==bundle_set_byte_array_element(b,"k1",1,"dd\0",3)); + assert(0==bundle_set_byte_array_element(b,"k1",2,"eee\0",4)); +/*try to add second array element again- over writing not allowed-fail */ + assert(0!=bundle_set_byte_array_element(b,"k1",1,"new\0",4)); + assert(EINVAL == errno ); +/*add fifth element - fail */ + assert(0!=bundle_set_byte_array_element(b,"k1",4,"gggg\0",5)); + assert(EINVAL == errno ); +/*bundle= NULL - fail */ + assert(0!=bundle_add_byte_array(b1,"key1",NULL,6)); + assert(EINVAL == errno ); +/*duplicate key - fail */ + assert(0!=bundle_add_byte_array(b,"k1",NULL,6)); + assert(EPERM == errno ); +/*empty key - fail */ + assert(0!=bundle_add_byte_array(b,"",NULL,6)); + assert(EKEYREJECTED == errno ); +/*No of elements = NULL - success */ + assert(0==bundle_add_byte_array(b,"k3",NULL,NULL)); +/*add new array with a different key and 6 elements -success */ + assert(0==bundle_add_byte_array(b,"k2",NULL,6)); +/* add fifth element- 1st/2nd/3rd/4th not yet added. */ + assert(0==bundle_set_byte_array_element(b,"k2",4,"ccc\0",4)); +/* bundle = NULL */ + assert(0!=bundle_set_byte_array_element(b1,"k2",0,"ccc\0",4)); + assert(EINVAL == errno ); +/* key = NULL */ + assert(0!=bundle_set_byte_array_element(b,NULL,1,"gggg\0",5)); + assert(EKEYREJECTED == errno ); +/* pass string instead of byte in value */ + assert(0==bundle_set_byte_array_element(b,"k2",3,"hello",6)); + assert(0==bundle_set_byte_array_element(b,"k2",5,"world",6));/*note size = size of string+ 1 (for \0) -- if \0 not added then juck characters appear while encode- decode */ + +// bundle_foreach(b,(void *)iterate_bundleforeach,NULL); + assert(0==bundle_free(b)); + return SUCCESS; + +} +int TC_bundle_get_byte() +{ + //printf("\n ====================================================================\n"); + //printf("\nTESTCASE :TC_bundle_get_byte"); + bundle *b=NULL; + const char *arr[]={"v1","v2","v3"}; + size_t len= -1; + void* ret_byte; + b=bundle_create(); + assert(NULL != b); + /* add elements */ + assert(0 == bundle_add_byte(b, "k1","aa\0",3)); + assert(0 == bundle_add_byte(b, "k2","bb\0",3)); + + assert(0 == bundle_add(b, "key1", "val1")); + assert(0==bundle_add_str_array(b,"key2",arr,3)); + assert(0==bundle_add_byte_array(b,"key3",NULL,4)); + assert(0==bundle_set_byte_array_element(b,"key3",0,"ccc\0",4)); +/*valid tests */ + assert(0==bundle_get_byte(b,"k1",&ret_byte,&len)); + assert(0==strcmp("aa",ret_byte)); + assert(3==len); + assert(0==bundle_get_byte(b,"k2",&ret_byte,&len)); + assert(0==strcmp("bb",ret_byte)); + assert(3==len); + assert(0==bundle_get_byte(b,"k2",NULL,&len)); + assert(3==len); + assert(0==bundle_get_byte(b,"k2",NULL,NULL)); +/*invalid tests */ + /* bundle= NULL */ + assert(0!=bundle_get_byte(NULL,"k1",&ret_byte,&len)); + assert(EINVAL == errno ); + /*key = empty */ + assert(0!=bundle_get_byte(b,"",&ret_byte,&len)); + assert(ENOKEY == errno ); + /*key does not exist */ + assert(0!=bundle_get_byte(b,"k3",&ret_byte,&len)); + assert(ENOKEY == errno ); + /*key = NULL */ + assert(0!=bundle_get_byte(b,NULL,&ret_byte,&len)); + assert(EKEYREJECTED == errno ); + /*pass the key for str type bundle-operation not supported */ + assert(0!=bundle_get_byte(b,"key1",&ret_byte,&len)); + assert(ENOTSUP == errno ); + /*pass the key for array type bundle */ + assert(0!=bundle_get_byte(b,"key2",&ret_byte,&len)); + assert(ENOTSUP == errno ); + assert(0!=bundle_get_byte(b,"key3",&ret_byte,&len)); + assert(ENOTSUP == errno ); + + assert(0==bundle_free(b)); + return SUCCESS; +} +#endif +/*API prototype changed */ +#if 0 +int TC_bundle_get_str_array() +{ + //printf("\n ====================================================================\n"); + //printf("\n TESTCASE :TC_bundle_get_str_array"); + bundle *b=NULL; + const char *arr[]={"v1","v2","v3"}; + char **str_arr=NULL; + int len = -1; + b=bundle_create(); + assert(NULL != b); +/* add elements */ + assert(0 == bundle_add(b, "k1", "val1")); + assert(0==bundle_add_str_array(b,"k2",arr,3)); + assert(0 == bundle_add_byte(b, "k3","hello\0",6)); + assert(0==bundle_add_byte_array(b,"k4",NULL,4)); + assert(0==bundle_set_byte_array_element(b,"k4",0,"ccc\0",4)); +/* valid case test */ + assert(0==bundle_get_str_array(b,"k2",&str_arr,&len)); + assert(0==strcmp("v1",str_arr[0])); + assert(0==strcmp("v2",str_arr[1])); + assert(3==len); + assert(3== (strlen(str_arr[0])+1)); + assert(3== (strlen(str_arr[1])+1)); + + assert(0==bundle_get_str_array(b,"k2",NULL,&len)); + assert(3==len); + assert(0==bundle_get_str_array(b,"k2",NULL,NULL)); +/* invalid cases test */ + /*bundle= null */ + assert(0!=bundle_get_str_array(NULL,"k2",&str_arr,&len)); + assert(EINVAL == errno ); + /*key = empty */ + assert(0!=bundle_get_str_array(b,"",&str_arr,&len)); + assert(ENOKEY == errno ); + /*invalid key */ + assert(0!=bundle_get_str_array(b,"key1",&str_arr,&len)); + assert(ENOKEY == errno ); + /*key = NULL */ + assert(0!=bundle_get_str_array(b,NULL,&str_arr,&len)); + assert(EKEYREJECTED == errno ); + /*key for invalid type of element */ + assert(0!=bundle_get_str_array(b,"k1",&str_arr,&len)); + assert(ENOTSUP == errno ); + assert(0!=bundle_get_str_array(b,"k3",&str_arr,&len)); + assert(ENOTSUP == errno ); + assert(0!=bundle_get_str_array(b,"k4",&str_arr,&len)); + assert(ENOTSUP == errno ); + + assert(0==bundle_free(b)); + return SUCCESS; +} +#endif +#if 1 +int TC_bundle_get_str_array() +{ + //printf("\n ====================================================================\n"); + //printf("\n TESTCASE :TC_bundle_get_str_array"); + bundle *b=NULL; + const char *arr[]={"v1","v2","v3"}; + const char **str_arr=NULL; + const char **str_arr1=NULL; + const char **str_arr2=NULL; + int len = -1; + b=bundle_create(); + assert(NULL != b); +/* add elements */ + assert(0 == bundle_add(b, "k1", "val1")); + assert(0==bundle_add_str_array(b,"k2",arr,3)); +/* valid case test */ + str_arr=bundle_get_str_array(b,"k2",&len); + /*printf("\nreturned array ele 1 is %s",str_arr[0]); + printf("\nreturned array ele 2 is %s",str_arr[1]); + printf("\nreturned array ele 3 is %s",str_arr[2]);*/ + assert(3==len); + //assert(0==strcmp("v1",str_arr[0])); + str_arr1=bundle_get_str_array(b,"k2",&len); + assert(3==len); + str_arr2=bundle_get_str_array(b,"k2",NULL); +/* invalid cases test */ + /*bundle= null */ + assert(NULL ==bundle_get_str_array(NULL,"k2",&len)); + assert(EINVAL == errno ); + /*key = empty */ + assert(NULL==bundle_get_str_array(b,"",&len)); + assert(ENOKEY == errno ); + /*invalid key */ + assert(NULL==bundle_get_str_array(b,"key1",&len)); + assert(ENOKEY == errno ); + /*key = NULL */ + assert(NULL==bundle_get_str_array(b,NULL,&len)); + assert(EKEYREJECTED == errno ); + /*key for invalid type of element */ + assert(NULL==bundle_get_str_array(b,"k1",&len)); + assert(ENOTSUP == errno ); + assert(0==bundle_free(b)); + return SUCCESS; +} +#endif +#if 0 +int TC_bundle_get_byte_array() +{ + //printf("\n ====================================================================\n"); + //printf("\nTESTCASE :TC_bundle_get_byte_array"); + bundle *b=NULL; + const char *arr[]={"v1","v2","v3"}; + void **byte_arr=NULL; + unsigned int len = -1; + unsigned int *ele_size= NULL; + b=bundle_create(); + assert(NULL != b); +/* add elements */ + assert(0 == bundle_add(b, "k1", "val1")); + assert(0==bundle_add_str_array(b,"k2",arr,3)); + assert(0 == bundle_add_byte(b, "k3","hello\0",6)); + assert(0==bundle_add_byte_array(b,"k4",NULL,4)); + assert(0==bundle_set_byte_array_element(b,"k4",0,"ccc\0",4)); + assert(0==bundle_set_byte_array_element(b,"k4",1,"dddd\0",5)); +/* valid case test */ + assert(0==bundle_get_byte_array(b,"k4",&byte_arr,&len,&ele_size)); + assert(0==strcmp("ccc",byte_arr[0])); + assert(0==strcmp("dddd",byte_arr[1])); + assert(4==len); + assert(4== (strlen(byte_arr[0])+1)); + assert(5== (strlen(byte_arr[1])+1)); + + assert(0==bundle_get_byte_array(b,"k4",NULL,&len,&ele_size)); + assert(4==len); + assert(0==bundle_get_byte_array(b,"k4",NULL,NULL,&ele_size)); +/* invalid cases test */ + /*bundle= null */ + assert(0!=bundle_get_byte_array(NULL,"k4",&byte_arr,&len,&ele_size)); + assert(EINVAL == errno ); + /*key = empty */ + assert(0!=bundle_get_byte_array(b,"",&byte_arr,&len,&ele_size)); + assert(ENOKEY == errno ); + /*invalid key */ + assert(0!=bundle_get_byte_array(b,"key1",&byte_arr,&len,&ele_size)); + assert(ENOKEY == errno ); + /*key = NULL */ + assert(0!=bundle_get_byte_array(b,NULL,&byte_arr,&len,&ele_size)); + assert(EKEYREJECTED == errno ); + /*key for invalid type of element */ + assert(0!=bundle_get_byte_array(b,"k1",&byte_arr,&len,&ele_size)); + assert(ENOTSUP == errno ); + assert(0!=bundle_get_byte_array(b,"k2",&byte_arr,&len,&ele_size)); + assert(ENOTSUP == errno ); + assert(0!=bundle_get_byte_array(b,"k3",&byte_arr,&len,&ele_size)); + assert(ENOTSUP == errno ); + + assert(0==bundle_free(b)); + return SUCCESS; +} +#endif +int TC_bundle_get_type() +{ + //printf("\n ====================================================================\n"); + //printf("\nTESTCASE: TC_bundle_get_type"); + char **array=NULL; + char buf[10]={0,}; + int no_of_ele=10; + int i=0; + bundle *b=NULL; + b=bundle_create(); + assert(NULL != b); + + /* add elements */ + assert(0 == bundle_add(b, "k1", "val1")); + array=(char **)malloc(no_of_ele*sizeof(char *)); + for (i=0;i +#include +#include +#include +#include "bundle.h" + +void test_bundle_create(void) +{ + bundle *b; + + b = bundle_create(); + assert(NULL != b); + + bundle_free(b); +} + +void test_bundle_add_get(void) +{ + bundle *b = NULL; + + /* new bundle */ + b = bundle_create(); + assert(0 == bundle_add(b, "key1", "val1")); + assert(0 == bundle_add(b, "key2", "val2")); + + assert(0 == strcmp("val2", bundle_get_val(b, "key2"))); + assert(2 == bundle_get_count(b)); + + /* key duplication check + * If key is already exist, raise error code, and ignore new val. + * old value is preserved. + */ + assert(0 != bundle_add(b, "key1", "val123")); + assert(EPERM == errno); + /* still has "val1" for "key1" */ + assert(0 == strcmp("val1", bundle_get_val(b, "key1"))); + /* still count is 2 */ + assert(2 == bundle_get_count(b)); + + /* 3rd val */ + bundle_add(b, "key3", "val3"); + assert(3 == bundle_get_count(b)); /* now 3 */ + + bundle_free(b); +} + +void test_bundle_add_invalid(void) +{ + bundle *b; + + assert(0 != bundle_add(NULL, "a", "b")); + assert(EINVAL == errno); + + b = bundle_create(); + assert(-1 == bundle_add(b, NULL, "val1")); + assert(EKEYREJECTED == errno); + + assert(0 != bundle_add(b, "key1", NULL)); + assert(EINVAL == errno); + + assert(0 != bundle_add(b, "", "aaa")); + assert(EKEYREJECTED == errno); + + bundle_free(b); +} + +void test_bundle_get_invalid(void) +{ + bundle *b; + + assert(NULL == bundle_get_val(NULL, "key1")); + assert(EINVAL == errno); + + b = bundle_create(); + + assert(NULL == bundle_get_val(b, "key4")); + assert(ENOKEY == errno); + + assert(NULL == bundle_get_val(NULL, "aaa")); + assert(EINVAL == errno); + + assert(NULL == bundle_get_val(b, NULL)); + assert(EKEYREJECTED == errno); + + bundle_free(b); +} + +void iter_f(const char *key, const char *val, void *data) +{ + char *keys[] = { "1", "2", "3" }; + char *vals[] = { "a", "b", "c" }; + int i; + + for (i = 0; i < 3; i++) { + if (0 == strcmp(key, keys[i])) { + assert(0 == strcmp(val, vals[i])); + break; + } + } +} + +void test_bundle_del(void) +{ + bundle *b; + + assert(0 != bundle_del(NULL, "key")); + assert(EINVAL == errno); + + b = bundle_create(); + + assert(0 != bundle_del(b, NULL)); + assert(EKEYREJECTED == errno); + + assert(0 != bundle_del(b, "")); + assert(EKEYREJECTED == errno); + + assert(0 != bundle_del(b, "key")); + assert(ENOKEY == errno); + + assert(0 == bundle_get_count(b)); + + bundle_add(b, "k1", "v1"); + const char *v = bundle_get_val(b, "k1"); + assert(NULL != v && 0 == strcmp("v1", v)); + + assert(1 == bundle_get_count(b)); + + assert(0 == bundle_del(b, "k1")); + assert(NULL == bundle_get_val(b, "k1")); + assert(ENOKEY == errno); + + assert(0 == bundle_get_count(b)); + + bundle_free(b); +} + +void test_bundle_iterate(void) +{ + bundle *b; + + b = bundle_create(); + + bundle_add(b, "1", "a"); + bundle_add(b, "2", "b"); + bundle_add(b, "3", "c"); + + bundle_iterate(b, iter_f, NULL); + + bundle_free(b); +} + +void test_bundle_encode_decode(void) +{ + bundle *b1, *b2; + bundle_raw *r; + int size_r; + + b1 = bundle_create(); + bundle_add(b1, "k1", "v1"); + bundle_add(b1, "k2", "v2"); + bundle_encode(b1, &r, &size_r); + + /* show serialized data */ + /* + char *c = r; + for(; c < r+size_r; c++) { + printf("%c", *c); + if ('\0' == *c) printf("\n"); + } + */ + + b2 = bundle_decode(r, size_r); + + assert(0 == strcmp(bundle_get_val(b1, "k1"), bundle_get_val(b2, "k1"))); + assert(0 == strcmp(bundle_get_val(b1, "k2"), bundle_get_val(b2, "k2"))); + + bundle_free(b1); + bundle_free(b2); + free(r); +} + +void test_bundle_2byte_chars(void) +{ + bundle *b; + char *k1 = "?ë„ë¦¬ì–¸ë£¨aaabb?¸ã…?°ss처푸?€"; + char *v1 = "?ˆã…‚짜ccc?œì–¸sss루퍼ë¬?; + char *k2 = "ljvvn?Œì±‚?¹ã…‡?´ì§•?„풐;ë¨?sdfxa?ã…£?ã…ë¦?; + char *v2 = "axs?´ã…‡?¼í¼?ë†”미ㅇ"; + + b = bundle_create(); + + bundle_add(b, k1, v1); + assert(0 == strcmp(v1, bundle_get_val(b, k1))); + bundle_add(b, k2, v2); + assert(0 == strcmp(v2, bundle_get_val(b, k2))); + + bundle_free(b); +} + +static void _dup_check_cb(const char *k, const char *v, void *data) +{ + bundle *b = (bundle *) data; + + assert(0 == strcmp(bundle_get_val(b, k), v)); +} + +void test_bundle_dup(void) +{ + bundle *b1, *b2; + b1 = bundle_create(); + bundle_add(b1, "k1", "v1"); + bundle_add(b1, "k2", "v2"); + + b2 = bundle_dup(b1); + + assert(NULL != b2); + bundle_iterate(b2, _dup_check_cb, b1); + assert(bundle_get_count(b1) == bundle_get_count(b2)); + + bundle_free(b1); + bundle_free(b2); +} + +void test_bundle_convert_argv(void) +{ + + bundle *b1, *b2; + + b1 = bundle_create(); + bundle_add(b1, "k1", "v1"); + bundle_add(b1, "k2", "v2"); + + /* export test */ + int argc = 0; + char **argv = NULL; + argc = bundle_export_to_argv(b1, &argv); + assert(5 == argc); + assert(NULL != argv); + assert(NULL == argv[0]); + assert(0 == strcmp("k1", argv[1]) && 0 == strcmp("v1", argv[2])); + assert(0 == strcmp("k2", argv[3]) && 0 == strcmp("v2", argv[4])); + assert(NULL == argv[5]); /* Last item must be NULL */ + + /* import test */ + b2 = bundle_import_from_argv(argc, argv); + assert(NULL != b2); + assert(2 == bundle_get_count(b2)); + assert(0 == strcmp("v1", bundle_get_val(b2, "k1"))); + assert(0 == strcmp("v2", bundle_get_val(b2, "k2"))); + + free(argv); + bundle_free(b1); + bundle_free(b2); +} + +int main(int argc, char **argv) +{ + test_bundle_create(); + test_bundle_add_get(); + test_bundle_add_invalid(); + test_bundle_get_invalid(); + test_bundle_del(); + test_bundle_iterate(); + test_bundle_encode_decode(); + test_bundle_2byte_chars(); + test_bundle_dup(); + test_bundle_convert_argv(); + + return 0; +} + -- 2.7.4