├── .gitignore ├── test ├── BUILD └── struct_test.cpp ├── src ├── struct_endian.c ├── struct_endian.h └── struct.c ├── WORKSPACE ├── BUILD ├── LICENSE ├── README.md ├── CMakeLists.txt └── include └── struct └── struct.h /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | *.lnt 3 | *.swp 4 | bazel-* 5 | -------------------------------------------------------------------------------- /test/BUILD: -------------------------------------------------------------------------------- 1 | 2 | cc_test( 3 | name = "struct_test", 4 | srcs = ["struct_test.cpp"], 5 | deps = [ 6 | "//:struct", 7 | "@com_google_googletest//:gtest_main" 8 | ], 9 | copts = ["-Iinclude/struct"], 10 | ) 11 | -------------------------------------------------------------------------------- /src/struct_endian.c: -------------------------------------------------------------------------------- 1 | #include "struct_endian.h" 2 | 3 | int struct_get_endian(void) 4 | { 5 | int i = 0x00000001; 6 | if (((char *)&i)[0]) { 7 | return STRUCT_ENDIAN_LITTLE; 8 | } else { 9 | return STRUCT_ENDIAN_BIG; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | 2 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 3 | 4 | http_archive( 5 | name = "com_google_googletest", 6 | url = "https://github.com/google/googletest/archive/release-1.12.1.zip", 7 | strip_prefix = "googletest-release-1.12.1", 8 | ) 9 | -------------------------------------------------------------------------------- /src/struct_endian.h: -------------------------------------------------------------------------------- 1 | #ifndef STRUCT_ENDIAN_INCLUDED 2 | #define STRUCT_ENDIAN_INCLUDED 3 | 4 | #define STRUCT_ENDIAN_NOT_SET 0 5 | #define STRUCT_ENDIAN_BIG 1 6 | #define STRUCT_ENDIAN_LITTLE 2 7 | 8 | extern int struct_get_endian(void); 9 | 10 | #endif /* !STRUCT_ENDIAN_INCLUDED */ 11 | -------------------------------------------------------------------------------- /BUILD: -------------------------------------------------------------------------------- 1 | 2 | cc_library( 3 | name = "struct", 4 | srcs = [ 5 | "src/struct.c", 6 | "src/struct_endian.c", 7 | "src/struct_endian.h" 8 | ], 9 | hdrs = ["include/struct/struct.h"], 10 | includes = ["include/struct"], 11 | strip_include_prefix = "include/struct", 12 | visibility = ["//visibility:public"] 13 | ) 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 choi won seok 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | `struct` is a binary data formatting library inspired by 4 | 'The Practice of Programming (Brian W. Kernighan, Rob Pike)' and 5 | Python struct module. 6 | 7 | ## Format 8 | 9 | `struct` uses following format characters (note that `struct` does not fully 10 | support the Python struct module's format): 11 | 12 | Table 1. Byte order 13 | 14 | Character | Byte order 15 | ----------|----------- 16 | `=` | native 17 | `<` | little-endian 18 | `>` | big-endian 19 | `!` | network (= big-endian) 20 | 21 | 22 | Table 2. Format characters 23 | 24 | Format | C/C++ Type | Standard size 25 | -------|--------------------|-------------- 26 | `b` | char | 1 27 | `B` | unsigned char | 1 28 | `h` | short | 2 29 | `H` | unsigned short | 2 30 | `i` | int | 4 31 | `I` | unsigned int | 4 32 | `l` | long | 4 33 | `L` | unsigned long | 4 34 | `q` | long long | 8 35 | `Q` | unsigned long long | 8 36 | `f` | float | 4 37 | `d` | double | 8 38 | `s` | char[] | 39 | `p` | char[] | 40 | `x` | pad bytes | 41 | `v` | go/pbuf svarint | 42 | `V` | go/pbuf varint | 43 | 44 | ## Pack 45 | 46 | ```c 47 | #include "struct.h" 48 | ... 49 | char buf1[BUFSIZ] = {'\0',}; 50 | char buf2[BUFSIZ] = {'\0',}; 51 | char str[BUFSIZ] = {'\0',}; 52 | char fmt[BUFSIZ] = {'\0',}; 53 | int val = 42; 54 | 55 | struct_pack(buf1, "i", val); 56 | 57 | strcpy(str, "test"); 58 | snprintf(fmt, sizeof(fmt), "%ds", strlen(str)); 59 | 60 | struct_pack(buf2, fmt, str); 61 | ``` 62 | 63 | ## Unpack 64 | 65 | ```c 66 | ... 67 | int rval; 68 | char rstr[32] = {'\0',}; 69 | 70 | struct_unpack(buf1, "i", &rval); 71 | 72 | struct_unpack(buf2, fmt, rstr); 73 | ``` 74 | 75 | # Install 76 | 77 | ## CMake 78 | 79 | ### Compile 80 | 81 | mkdir build 82 | cd build 83 | cmake .. 84 | make 85 | make install 86 | 87 | headers: `build/release/include/struct/`. 88 | library: `build/release/lib/`. 89 | 90 | ### Test 91 | 92 | cmake -DSTRUCT_BUILD_TEST=ON .. 93 | make 94 | make test 95 | 96 | or run `struct_test`. 97 | 98 | valgrind memory check: 99 | 100 | ctest -T memcheck 101 | 102 | ## Bazel 103 | 104 | ### Compile 105 | 106 | bazel build //:struct 107 | 108 | ### Test 109 | 110 | bazel test //test:struct_test 111 | 112 | or 113 | 114 | bazel test --test_output=all //test:struct_test 115 | 116 | you can use `git_repository` to fetch `struct` library. 117 | 118 | WORKSPACE: 119 | 120 | load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") 121 | 122 | git_repository( 123 | name = "struct", 124 | branch = "master", 125 | remote = "https://github.com/svperbeast/struct", 126 | ) 127 | 128 | BUILD: 129 | 130 | cc_binary( 131 | name = ..., 132 | srcs = [...], 133 | deps = [ 134 | "@struct//:struct", 135 | ], 136 | ) 137 | 138 | # References 139 | 140 | [The Practice of Programming (9.1 Formatting Data)](http://www.amazon.com/Practice-Programming-Addison-Wesley-Professional-Computing/dp/020161586X/ref=sr_1_1?ie=UTF8&qid=1359350725&sr=8-1&keywords=practice+of+programming "The Practice of Programming") 141 | 142 | [Python struct](http://docs.python.org/2/library/struct.html#module-struct "Python struct module") 143 | 144 | # License 145 | Code released under [the MIT license](https://github.com/svperbeast/struct/blob/master/LICENSE). 146 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1) 2 | 3 | project (struct LANGUAGES C CXX) 4 | 5 | set (CMAKE_C_STANDARD 99) 6 | set (CMAKE_C_EXTENSIONS OFF) 7 | set (CMAKE_C_STANDARD_REQUIRED ON) 8 | 9 | # 10 | # [Option(s)] 11 | # STRUCT_BUILD_TEST: build googletest and test programs 12 | # (e.g., cmake -DSTRUCT_BUILD_TEST=ON ..). 13 | # 14 | 15 | find_package (Threads REQUIRED) 16 | 17 | option (STRUCT_BUILD_TEST "build googletest and test programs" OFF) 18 | 19 | if (STRUCT_BUILD_TEST) 20 | include(ExternalProject) 21 | # googletest 22 | ExternalProject_Add ( 23 | googletest 24 | GIT_REPOSITORY https://github.com/google/googletest.git 25 | GIT_TAG release-1.12.1 26 | UPDATE_COMMAND "" 27 | INSTALL_COMMAND "" 28 | LOG_DOWNLOAD ON 29 | LOG_CONFIGURE ON 30 | LOG_BUILD ON 31 | ) 32 | set_target_properties(googletest PROPERTIES EXCLUDE_FROM_ALL TRUE) 33 | ExternalProject_Get_Property (googletest source_dir) 34 | set (GTEST_INCLUDE_DIRS "${source_dir}/googletest/include") 35 | ExternalProject_Get_Property (googletest binary_dir) 36 | set (GTEST_LINK_DIRS "${binary_dir}/lib") 37 | 38 | 39 | endif(STRUCT_BUILD_TEST) 40 | 41 | # remove -rdynamic 42 | set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) 43 | set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) 44 | 45 | include_directories ("${struct_SOURCE_DIR}/include" 46 | ${GTEST_INCLUDE_DIRS} 47 | ) 48 | 49 | link_directories(${GTEST_LINK_DIRS}) 50 | 51 | add_library (struct 52 | src/struct_endian.c 53 | src/struct.c 54 | ) 55 | 56 | set_target_properties (struct PROPERTIES 57 | COMPILE_FLAGS 58 | "${CMAKE_C_FLAGS} -O2 -Wall" 59 | ) 60 | 61 | install (TARGETS 62 | struct 63 | PERMISSIONS 64 | OWNER_READ OWNER_WRITE OWNER_EXECUTE 65 | GROUP_READ GROUP_WRITE GROUP_EXECUTE 66 | WORLD_READ WORLD_EXECUTE 67 | DESTINATION 68 | "${CMAKE_BINARY_DIR}/release/lib" 69 | EXPORT 70 | struct 71 | ) 72 | 73 | set ( 74 | INCLUDE_INSTALL_DIR 75 | "${CMAKE_BINARY_DIR}/release/include/struct" 76 | ) 77 | 78 | set ( 79 | SRC_INCLUDE_SUPER_DIR 80 | "${struct_SOURCE_DIR}/include" 81 | ) 82 | 83 | set ( 84 | SRC_INCLUDE_DIR 85 | "${SRC_INCLUDE_SUPER_DIR}/struct" 86 | ) 87 | 88 | install (FILES 89 | "${SRC_INCLUDE_DIR}/struct.h" 90 | DESTINATION 91 | "${INCLUDE_INSTALL_DIR}" 92 | ) 93 | 94 | target_include_directories ( 95 | struct 96 | PUBLIC 97 | "$" 98 | $ 99 | ) 100 | 101 | export ( 102 | TARGETS 103 | struct 104 | FILE 105 | "${CMAKE_BINARY_DIR}/struct-config.cmake" 106 | ) 107 | 108 | export ( 109 | PACKAGE 110 | struct 111 | ) 112 | 113 | if (STRUCT_BUILD_TEST) 114 | include (CTest) 115 | enable_testing () 116 | 117 | set (MEMORYCHECK_COMMAND valgrind) 118 | set (MEMORYCHECK_COMMAND_OPTIONS "--tool=memcheck --leack-check=yes") 119 | 120 | add_executable (struct_test 121 | test/struct_test.cpp 122 | ) 123 | find_package(Threads REQUIRED) 124 | 125 | target_link_libraries (struct_test struct gtest ${CMAKE_THREAD_LIBS_INIT}) 126 | 127 | set_target_properties (struct_test PROPERTIES 128 | RUNTIME_OUTPUT_DIRECTORY 129 | "${CMAKE_BINARY_DIR}" 130 | ) 131 | add_dependencies(struct_test googletest) 132 | 133 | add_test (StructTest "${CMAKE_BINARY_DIR}/struct_test") 134 | endif (STRUCT_BUILD_TEST) 135 | -------------------------------------------------------------------------------- /include/struct/struct.h: -------------------------------------------------------------------------------- 1 | #ifndef STRUCT_INCLUDED 2 | #define STRUCT_INCLUDED 3 | /* 4 | * struct.h 5 | * 6 | * Created on: 2011. 5. 2. 7 | * Author: wonseok choi (svperbeast@gmail.com) 8 | * 9 | * Interpret strings as packed binary data 10 | * 11 | * Table 1. Byte order 12 | * ---------------------------------- 13 | * Character | Byte order 14 | * ----------+----------------------- 15 | * = | native 16 | * ----------+----------------------- 17 | * < | little-endian 18 | * ----------+----------------------- 19 | * > | big-endian 20 | * ----------+----------------------- 21 | * ! | network (= big-endian) 22 | * ---------------------------------- 23 | * 24 | * Table 2. Format characters 25 | * ------------------------------------------- 26 | * Format | C/C++ Type | Standard size 27 | * -------+--------------------+-------------- 28 | * b | char | 1 29 | * -------+--------------------+-------------- 30 | * B | unsigned char | 1 31 | * -------+--------------------+-------------- 32 | * h | short | 2 33 | * -------+--------------------+-------------- 34 | * H | unsigned short | 2 35 | * -------+--------------------+-------------- 36 | * i | int | 4 37 | * -------+--------------------+-------------- 38 | * I | unsigned int | 4 39 | * -------+--------------------+-------------- 40 | * l | long | 4 41 | * -------+--------------------+-------------- 42 | * L | unsigned long | 4 43 | * -------+--------------------+-------------- 44 | * q | long long | 8 45 | * -------+--------------------+-------------- 46 | * Q | unsigned long long | 8 47 | * -------+--------------------+-------------- 48 | * f | float | 4 49 | * -------+--------------------+-------------- 50 | * d | double | 8 51 | * -------+--------------------+-------------- 52 | * s | char[] | 53 | * -------+--------------------+-------------- 54 | * p | char[] | 55 | * -------+--------------------+-------------- 56 | * x | pad bytes | 57 | * -------+--------------------+-------------- 58 | * v | signed varint | 59 | * -------+--------------------+-------------- 60 | * V | unsigned varint | 61 | * ----------------------------+-------------- 62 | * 63 | * 64 | * A format character may be preceded by an integral repeat count. 65 | * For example, the format string '4h' means exactly the same as 'hhhh'. 66 | * 67 | * For the 's' format character, the count is interpreted as the size of the 68 | * string, not a repeat count like for the other format characters. 69 | * For example, '10s' means a single 10-byte string. 70 | * 71 | * Example 1. pack/unpack int type value. 72 | * 73 | * char buf[BUFSIZ] = {0, }; 74 | * int val = 0x12345678; 75 | * int oval; 76 | * 77 | * struct_pack(buf, "i", val); 78 | * struct_unpack(buf, "i", &oval); 79 | * 80 | * Example 2. pack/unpack a string. 81 | * 82 | * char buf[BUFSIZ] = {0, }; 83 | * char str[32] = {'\0', }; 84 | * char fmt[32] = {'\0', }; 85 | * char ostr[32] = {'\0', }; 86 | * 87 | * strcpy(str, "test"); 88 | * sprintf(fmt, "%ds", strlen(str)); 89 | * 90 | * struct_pack(buf, fmt, str); 91 | * struct_unpack(buf, fmt, ostr); 92 | * 93 | */ 94 | 95 | #ifdef __cplusplus 96 | extern "C" { 97 | #endif 98 | 99 | /** 100 | * @brief pack data 101 | * @return the number of bytes encoded on success, -1 on failure. 102 | */ 103 | extern int struct_pack(void *buf, const char *fmt, ...); 104 | 105 | /** 106 | * @brief pack data with offset 107 | * @return the number of bytes encoded on success, -1 on failure. 108 | */ 109 | extern int struct_pack_into(int offset, void *buf, const char *fmt, ...); 110 | 111 | /** 112 | * @brief unpack data 113 | * @return the number of bytes decoded on success, -1 on failure. 114 | */ 115 | extern int struct_unpack(const void *buf, const char *fmt, ...); 116 | 117 | /** 118 | * @brief unpack data with offset 119 | * @return the number of bytes decoded on success, -1 on failure. 120 | */ 121 | extern int struct_unpack_from( 122 | int offset, 123 | const void *buf, 124 | const char *fmt, 125 | ...); 126 | 127 | /** 128 | * @brief calculate the size of a format string 129 | * @return the number of bytes needed by the format string on success, 130 | * -1 on failure. 131 | * 132 | * make sure that the return value is > 0, before using it. 133 | */ 134 | extern int struct_calcsize(const char *fmt); 135 | 136 | #ifdef __cplusplus 137 | } 138 | #endif 139 | 140 | #endif /* !STRUCT_INCLUDED */ 141 | -------------------------------------------------------------------------------- /src/struct.c: -------------------------------------------------------------------------------- 1 | #include "struct.h" 2 | #include "struct_endian.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define IEEE754_32_NAN 0x7FC00000 13 | #define IEEE754_32_INF 0x7F800000 14 | #define IEEE754_32_NEG_INF 0xFF800000 15 | 16 | #define IEEE754_64_NAN 0x7FF8000000000000 17 | #define IEEE754_64_INF 0x7FF0000000000000 18 | #define IEEE754_64_NEG_INF 0xFFF0000000000000 19 | 20 | // refer to 21 | // http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#serialization 22 | // - Beej's Guide to Network Programming 23 | // 24 | // macros for packing floats and doubles: 25 | #define PACK_IEEE754_32(f) (pack_ieee754((f), 32, 8)) 26 | #define PACK_IEEE754_64(f) (pack_ieee754((f), 64, 11)) 27 | #define UNPACK_IEEE754_32(i) (unpack_ieee754((i), 32, 8)) 28 | #define UNPACK_IEEE754_64(i) (unpack_ieee754((i), 64, 11)) 29 | 30 | #define INIT_REPETITION(_x) int _struct_rep = 0 31 | 32 | #define BEGIN_REPETITION(_x) do { _struct_rep-- 33 | 34 | #define END_REPETITION(_x) } while(_struct_rep > 0) 35 | 36 | #define INC_REPETITION(_x) _struct_rep = _struct_rep * 10 + (*p - '0') 37 | 38 | #define CLEAR_REPETITION(_x) _struct_rep = 0 39 | 40 | static int myendian = STRUCT_ENDIAN_NOT_SET; 41 | 42 | static void struct_init(void) 43 | { 44 | myendian = struct_get_endian(); 45 | } 46 | 47 | static uint64_t pack_ieee754(long double f, 48 | unsigned int bits, unsigned int expbits) 49 | { 50 | long double fnorm; 51 | int shift; 52 | long long sign; 53 | long long exp; 54 | long long significand; 55 | unsigned int significandbits = bits - expbits - 1; // -1 for sign bit 56 | 57 | int isinf_ret = isinf(f); 58 | if (isinf_ret != 0) { 59 | // isinf(f) returns 1 if f is positive infinity, 60 | // -1 if f is negative infinity. 61 | if (bits == 32) { 62 | return (isinf_ret == 1) ? IEEE754_32_INF : IEEE754_32_NEG_INF; 63 | } else { 64 | return (isinf_ret == 1) ? IEEE754_64_INF : IEEE754_64_NEG_INF; 65 | } 66 | } 67 | 68 | if (isnan(f)) { 69 | if (bits == 32) { 70 | return IEEE754_32_NAN; 71 | } else { 72 | return IEEE754_64_NAN; 73 | } 74 | } 75 | 76 | if (f == 0.0) { 77 | return 0; // get this special case out of the way 78 | } 79 | 80 | // check sign and begin normalization 81 | if (f < 0) { 82 | sign = 1; 83 | fnorm = -f; 84 | } else { 85 | sign = 0; 86 | fnorm = f; 87 | } 88 | 89 | // get the normalized form of f and track the exponent 90 | shift = 0; 91 | while (fnorm >= 2.0) { 92 | fnorm /= 2.0; 93 | shift++; 94 | } 95 | while (fnorm < 1.0) { 96 | fnorm *= 2.0; 97 | shift--; 98 | } 99 | fnorm = fnorm - 1.0; 100 | 101 | // calculate the binary form (non-float) of the significand data 102 | significand = (long long)(fnorm * ((1LL << significandbits) + 0.5F)); 103 | 104 | // get the biased exponent 105 | // shift + bias 106 | exp = shift + ((1LL << (expbits - 1)) - 1); 107 | 108 | // return the final answer 109 | return (sign << (bits - 1U)) | (exp << (bits - expbits - 1U)) | significand; 110 | } 111 | 112 | static long double unpack_ieee754(uint64_t i, 113 | unsigned int bits, unsigned int expbits) 114 | { 115 | long double result; 116 | long long shift; 117 | unsigned int bias; 118 | unsigned int significandbits = bits - expbits - 1; // -1 for sign bit 119 | 120 | if (i == 0) { 121 | return 0.0; 122 | } 123 | 124 | if (bits == 32) { 125 | if (i == IEEE754_32_NAN) { 126 | return NAN; 127 | } 128 | 129 | if (i == IEEE754_32_INF) { 130 | return INFINITY; 131 | } 132 | 133 | if (i == IEEE754_32_NEG_INF) { 134 | return -INFINITY; 135 | } 136 | } else { 137 | if (i == IEEE754_64_NAN) { 138 | return NAN; 139 | } 140 | 141 | if (i == IEEE754_64_INF) { 142 | return INFINITY; 143 | } 144 | 145 | if (i == IEEE754_64_NEG_INF) { 146 | return -INFINITY; 147 | } 148 | } 149 | 150 | // pull the significand 151 | result = (i & ((1LL << significandbits) - 1)); // mask 152 | result /= (1LL << significandbits); // convert back to float 153 | result += 1.0F; // add the one back on 154 | 155 | // deal with the exponent 156 | bias = (1 << (expbits - 1)) - 1; 157 | shift = ((i >> significandbits) & ((1LL << expbits) - 1)) - bias; 158 | while (shift > 0) { 159 | result *= 2.0; 160 | shift--; 161 | } 162 | while (shift < 0) { 163 | result /= 2.0; 164 | shift++; 165 | } 166 | 167 | // sign it 168 | result *= ((i >> (bits - 1)) & 1) ? -1.0 : 1.0; 169 | 170 | return result; 171 | } 172 | 173 | static void pack_int16_t(unsigned char **bp, uint16_t val, int endian) 174 | { 175 | if (endian == myendian) { 176 | *((*bp)++) = val; 177 | *((*bp)++) = val >> 8; 178 | } else { 179 | *((*bp)++) = val >> 8; 180 | *((*bp)++) = val; 181 | } 182 | } 183 | 184 | static void pack_int32_t(unsigned char **bp, uint32_t val, int endian) 185 | { 186 | if (endian == myendian) { 187 | *((*bp)++) = val; 188 | *((*bp)++) = val >> 8; 189 | *((*bp)++) = val >> 16; 190 | *((*bp)++) = val >> 24; 191 | } else { 192 | *((*bp)++) = val >> 24; 193 | *((*bp)++) = val >> 16; 194 | *((*bp)++) = val >> 8; 195 | *((*bp)++) = val; 196 | } 197 | } 198 | 199 | static void pack_int64_t(unsigned char **bp, uint64_t val, int endian) 200 | { 201 | if (endian == myendian) { 202 | *((*bp)++) = val; 203 | *((*bp)++) = val >> 8; 204 | *((*bp)++) = val >> 16; 205 | *((*bp)++) = val >> 24; 206 | *((*bp)++) = val >> 32; 207 | *((*bp)++) = val >> 40; 208 | *((*bp)++) = val >> 48; 209 | *((*bp)++) = val >> 56; 210 | } else { 211 | *((*bp)++) = val >> 56; 212 | *((*bp)++) = val >> 48; 213 | *((*bp)++) = val >> 40; 214 | *((*bp)++) = val >> 32; 215 | *((*bp)++) = val >> 24; 216 | *((*bp)++) = val >> 16; 217 | *((*bp)++) = val >> 8; 218 | *((*bp)++) = val; 219 | } 220 | } 221 | 222 | static void pack_float(unsigned char **bp, float val, int endian) 223 | { 224 | uint64_t ieee754_encoded_val = PACK_IEEE754_32(val); 225 | pack_int32_t(bp, ieee754_encoded_val, endian); 226 | } 227 | 228 | static void pack_double(unsigned char **bp, double val, int endian) 229 | { 230 | uint64_t ieee754_encoded_val = PACK_IEEE754_64(val); 231 | pack_int64_t(bp, ieee754_encoded_val, endian); 232 | } 233 | 234 | static void pack_varint(unsigned char **bp, uint64_t val, int endian) 235 | { 236 | for (size_t bytes = 0; val >= 0x80 && bytes < 10; val >>= 7, bytes++) 237 | *((*bp)++) = val | 0x80; 238 | *((*bp)++) = val; 239 | } 240 | 241 | static void pack_signed_varint(unsigned char **bp, int64_t val, int endian) 242 | { 243 | uint64_t uval = (uint64_t)val << 1ull; 244 | if (val < 0) 245 | uval = ~uval; 246 | pack_varint(bp, uval, endian); 247 | } 248 | 249 | static void unpack_int16_t(const unsigned char **bp, int16_t *dst, int endian) 250 | { 251 | uint16_t val; 252 | if (endian == myendian) { 253 | val = *((*bp)++); 254 | val |= (uint16_t)(*((*bp)++)) << 8; 255 | } else { 256 | val = (uint16_t)(*((*bp)++)) << 8; 257 | val |= *((*bp)++); 258 | } 259 | if (val <= 0x7fffU) { 260 | *dst = val; 261 | } else { 262 | *dst = -1 - (int16_t)(0xffffU - val); 263 | } 264 | } 265 | 266 | static void unpack_uint16_t(const unsigned char **bp, uint16_t *dst, int endian) 267 | { 268 | if (endian == myendian) { 269 | *dst = *((*bp)++); 270 | *dst |= (uint16_t)(*((*bp)++)) << 8; 271 | } else { 272 | *dst = (uint16_t)(*((*bp)++)) << 8; 273 | *dst |= *((*bp)++); 274 | } 275 | } 276 | 277 | static void unpack_int32_t(const unsigned char **bp, int32_t *dst, int endian) 278 | { 279 | uint32_t val; 280 | if (endian == myendian) { 281 | val = *((*bp)++); 282 | val |= (uint32_t)(*((*bp)++)) << 8; 283 | val |= (uint32_t)(*((*bp)++)) << 16; 284 | val |= (uint32_t)(*((*bp)++)) << 24; 285 | } else { 286 | val = *((*bp)++) << 24; 287 | val |= (uint32_t)(*((*bp)++)) << 16; 288 | val |= (uint32_t)(*((*bp)++)) << 8; 289 | val |= (uint32_t)(*((*bp)++)); 290 | } 291 | if (val <= 0x7fffffffU) { 292 | *dst = val; 293 | } else { 294 | *dst = -1 - (int32_t)(0xffffffffU - val); 295 | } 296 | } 297 | 298 | static void unpack_uint32_t(const unsigned char **bp, uint32_t *dst, int endian) 299 | { 300 | if (endian == myendian) { 301 | *dst = *((*bp)++); 302 | *dst |= (uint32_t)(*((*bp)++)) << 8; 303 | *dst |= (uint32_t)(*((*bp)++)) << 16; 304 | *dst |= (uint32_t)(*((*bp)++)) << 24; 305 | } else { 306 | *dst = *((*bp)++) << 24; 307 | *dst |= (uint32_t)(*((*bp)++)) << 16; 308 | *dst |= (uint32_t)(*((*bp)++)) << 8; 309 | *dst |= (uint32_t)(*((*bp)++)); 310 | } 311 | } 312 | 313 | static void unpack_int64_t(const unsigned char **bp, int64_t *dst, int endian) 314 | { 315 | uint64_t val; 316 | if (endian == myendian) { 317 | val = *((*bp)++); 318 | val |= (uint64_t)(*((*bp)++)) << 8; 319 | val |= (uint64_t)(*((*bp)++)) << 16; 320 | val |= (uint64_t)(*((*bp)++)) << 24; 321 | val |= (uint64_t)(*((*bp)++)) << 32; 322 | val |= (uint64_t)(*((*bp)++)) << 40; 323 | val |= (uint64_t)(*((*bp)++)) << 48; 324 | val |= (uint64_t)(*((*bp)++)) << 56; 325 | } else { 326 | val = (uint64_t)(*((*bp)++)) << 56; 327 | val |= (uint64_t)(*((*bp)++)) << 48; 328 | val |= (uint64_t)(*((*bp)++)) << 40; 329 | val |= (uint64_t)(*((*bp)++)) << 32; 330 | val |= (uint64_t)(*((*bp)++)) << 24; 331 | val |= (uint64_t)(*((*bp)++)) << 16; 332 | val |= (uint64_t)(*((*bp)++)) << 8; 333 | val |= *((*bp)++); 334 | } 335 | if (val <= 0x7fffffffffffffffULL) { 336 | *dst = val; 337 | } else { 338 | *dst = -1 - (int64_t)(0xffffffffffffffffULL - val); 339 | } 340 | } 341 | 342 | static void unpack_uint64_t(const unsigned char **bp, uint64_t *dst, int endian) 343 | { 344 | if (endian == myendian) { 345 | *dst = *((*bp)++); 346 | *dst |= (uint64_t)(*((*bp)++)) << 8; 347 | *dst |= (uint64_t)(*((*bp)++)) << 16; 348 | *dst |= (uint64_t)(*((*bp)++)) << 24; 349 | *dst |= (uint64_t)(*((*bp)++)) << 32; 350 | *dst |= (uint64_t)(*((*bp)++)) << 40; 351 | *dst |= (uint64_t)(*((*bp)++)) << 48; 352 | *dst |= (uint64_t)(*((*bp)++)) << 56; 353 | } else { 354 | *dst = (uint64_t)(*((*bp)++)) << 56; 355 | *dst |= (uint64_t)(*((*bp)++)) << 48; 356 | *dst |= (uint64_t)(*((*bp)++)) << 40; 357 | *dst |= (uint64_t)(*((*bp)++)) << 32; 358 | *dst |= (uint64_t)(*((*bp)++)) << 24; 359 | *dst |= (uint64_t)(*((*bp)++)) << 16; 360 | *dst |= (uint64_t)(*((*bp)++)) << 8; 361 | *dst |= *((*bp)++); 362 | } 363 | } 364 | 365 | static void unpack_float(const unsigned char **bp, float *dst, int endian) 366 | { 367 | uint32_t ieee754_encoded_val = 0; 368 | unpack_uint32_t(bp, &ieee754_encoded_val, endian); 369 | *dst = UNPACK_IEEE754_32(ieee754_encoded_val); 370 | } 371 | 372 | static void unpack_double(const unsigned char **bp, double *dst, int endian) 373 | { 374 | uint64_t ieee754_encoded_val = 0; 375 | unpack_uint64_t(bp, &ieee754_encoded_val, endian); 376 | *dst = UNPACK_IEEE754_64(ieee754_encoded_val); 377 | } 378 | 379 | static void unpack_varint(const unsigned char **bp, uint64_t *dst, int endian) 380 | { 381 | *dst = 0; 382 | for (size_t bits = 0; bits <= 63; bits += 7, (*bp)++) { 383 | *dst |= (uint64_t)((*bp)[0] & 0x7f) << bits; 384 | if (!((*bp)[0] & 0x80)) 385 | break; 386 | } 387 | (*bp)++; 388 | } 389 | 390 | static void unpack_signed_varint(const unsigned char **bp, int64_t *dst, int endian) 391 | { 392 | uint64_t uval; 393 | unpack_varint(bp, &uval, endian); 394 | *dst = (int64_t)(uval >> 1); 395 | if ((uval & 1) != 0) 396 | *dst = ~*dst; 397 | } 398 | 399 | static int pack_va_list(unsigned char *buf, int offset, const char *fmt, 400 | va_list args) 401 | { 402 | INIT_REPETITION(); 403 | const char *p; 404 | unsigned char *bp; 405 | int *ep = &myendian; 406 | int endian; 407 | 408 | char b; 409 | unsigned char B; 410 | int16_t h; 411 | uint16_t H; 412 | int32_t l; 413 | uint32_t L; 414 | int64_t q; 415 | uint64_t Q; 416 | float f; 417 | double d; 418 | char *s; 419 | int64_t v; 420 | uint64_t V; 421 | 422 | if (STRUCT_ENDIAN_NOT_SET == myendian) { 423 | struct_init(); 424 | } 425 | 426 | /* 427 | * 'char' and 'short' values, they must be extracted as 'int's, 428 | * because C promotes 'char' and 'short' arguments to 'int' when they are 429 | * represented by an ellipsis ... parameter. 430 | */ 431 | 432 | bp = buf + offset; 433 | for (p = fmt; *p != '\0'; p++) { 434 | switch (*p) { 435 | case '=': /* native */ 436 | ep = &myendian; 437 | break; 438 | case '<': /* little-endian */ 439 | endian = STRUCT_ENDIAN_LITTLE; 440 | ep = &endian; 441 | break; 442 | case '>': /* big-endian */ 443 | endian = STRUCT_ENDIAN_BIG; 444 | ep = &endian; 445 | break; 446 | case '!': /* network (= big-endian) */ 447 | endian = STRUCT_ENDIAN_BIG; 448 | ep = &endian; 449 | break; 450 | case 'b': 451 | BEGIN_REPETITION(); 452 | b = va_arg(args, int); 453 | *bp++ = b; 454 | END_REPETITION(); 455 | break; 456 | case 'B': 457 | BEGIN_REPETITION(); 458 | B = va_arg(args, unsigned int); 459 | *bp++ = B; 460 | END_REPETITION(); 461 | break; 462 | case 'h': 463 | BEGIN_REPETITION(); 464 | h = va_arg(args, int); 465 | pack_int16_t(&bp, h, *ep); 466 | END_REPETITION(); 467 | break; 468 | case 'H': 469 | BEGIN_REPETITION(); 470 | H = va_arg(args, int); 471 | pack_int16_t(&bp, H, *ep); 472 | END_REPETITION(); 473 | break; 474 | case 'i': /* fall through */ 475 | case 'l': 476 | BEGIN_REPETITION(); 477 | l = va_arg(args, int32_t); 478 | pack_int32_t(&bp, l, *ep); 479 | END_REPETITION(); 480 | break; 481 | case 'I': /* fall through */ 482 | case 'L': 483 | BEGIN_REPETITION(); 484 | L = va_arg(args, uint32_t); 485 | pack_int32_t(&bp, L, *ep); 486 | END_REPETITION(); 487 | break; 488 | case 'q': 489 | BEGIN_REPETITION(); 490 | q = va_arg(args, int64_t); 491 | pack_int64_t(&bp, q, *ep); 492 | END_REPETITION(); 493 | break; 494 | case 'Q': 495 | BEGIN_REPETITION(); 496 | Q = va_arg(args, uint64_t); 497 | pack_int64_t(&bp, Q, *ep); 498 | END_REPETITION(); 499 | break; 500 | case 'f': 501 | BEGIN_REPETITION(); 502 | f = va_arg(args, double); 503 | pack_float(&bp, f, *ep); 504 | END_REPETITION(); 505 | break; 506 | case 'd': 507 | BEGIN_REPETITION(); 508 | d = va_arg(args, double); 509 | pack_double(&bp, d, *ep); 510 | END_REPETITION(); 511 | break; 512 | case 's': /* fall through */ 513 | case 'p': 514 | { 515 | int i = 0; 516 | s = va_arg(args, char*); 517 | BEGIN_REPETITION(); 518 | *bp++ = s[i++]; 519 | END_REPETITION(); 520 | } 521 | break; 522 | case 'x': 523 | BEGIN_REPETITION(); 524 | *bp++ = 0; 525 | END_REPETITION(); 526 | break; 527 | case 'v': 528 | BEGIN_REPETITION(); 529 | v = va_arg(args, int64_t); 530 | pack_signed_varint(&bp, v, *ep); 531 | END_REPETITION(); 532 | break; 533 | case 'V': 534 | BEGIN_REPETITION(); 535 | V = va_arg(args, uint64_t); 536 | pack_varint(&bp, V, *ep); 537 | END_REPETITION(); 538 | break; 539 | default: 540 | if (isdigit((int)*p)) { 541 | INC_REPETITION(); 542 | } else { 543 | return -1; 544 | } 545 | } 546 | 547 | if (!isdigit((int)*p)) { 548 | CLEAR_REPETITION(); 549 | } 550 | } 551 | return (bp - buf); 552 | } 553 | 554 | static int unpack_va_list( 555 | const unsigned char *buf, 556 | int offset, 557 | const char *fmt, 558 | va_list args) 559 | { 560 | INIT_REPETITION(); 561 | const char *p; 562 | const unsigned char *bp; 563 | int *ep = &myendian; 564 | int endian; 565 | 566 | char *b; 567 | unsigned char *B; 568 | int16_t *h; 569 | uint16_t *H; 570 | int32_t *l; 571 | uint32_t *L; 572 | int64_t *q; 573 | uint64_t *Q; 574 | float *f; 575 | double *d; 576 | char *s; 577 | int64_t *v; 578 | uint64_t *V; 579 | 580 | if (STRUCT_ENDIAN_NOT_SET == myendian) { 581 | struct_init(); 582 | } 583 | 584 | bp = buf + offset; 585 | for (p = fmt; *p != '\0'; p++) { 586 | switch (*p) { 587 | case '=': /* native */ 588 | ep = &myendian; 589 | break; 590 | case '<': /* little-endian */ 591 | endian = STRUCT_ENDIAN_LITTLE; 592 | ep = &endian; 593 | break; 594 | case '>': /* big-endian */ 595 | endian = STRUCT_ENDIAN_BIG; 596 | ep = &endian; 597 | break; 598 | case '!': /* network (= big-endian) */ 599 | endian = STRUCT_ENDIAN_BIG; 600 | ep = &endian; 601 | break; 602 | case 'b': 603 | BEGIN_REPETITION(); 604 | b = va_arg(args, char*); 605 | *b = *bp++; 606 | END_REPETITION(); 607 | break; 608 | case 'B': 609 | BEGIN_REPETITION(); 610 | B = va_arg(args, unsigned char*); 611 | *B = *bp++; 612 | END_REPETITION(); 613 | break; 614 | case 'h': 615 | BEGIN_REPETITION(); 616 | h = va_arg(args, int16_t*); 617 | unpack_int16_t(&bp, h, *ep); 618 | END_REPETITION(); 619 | break; 620 | case 'H': 621 | BEGIN_REPETITION(); 622 | H = va_arg(args, uint16_t*); 623 | unpack_uint16_t(&bp, H, *ep); 624 | END_REPETITION(); 625 | break; 626 | case 'i': /* fall through */ 627 | case 'l': 628 | BEGIN_REPETITION(); 629 | l = va_arg(args, int32_t*); 630 | unpack_int32_t(&bp, l, *ep); 631 | END_REPETITION(); 632 | break; 633 | case 'I': /* fall through */ 634 | case 'L': 635 | BEGIN_REPETITION(); 636 | L = va_arg(args, uint32_t*); 637 | unpack_uint32_t(&bp, L, *ep); 638 | END_REPETITION(); 639 | break; 640 | case 'q': 641 | BEGIN_REPETITION(); 642 | q = va_arg(args, int64_t*); 643 | unpack_int64_t(&bp, q, *ep); 644 | END_REPETITION(); 645 | break; 646 | case 'Q': 647 | BEGIN_REPETITION(); 648 | Q = va_arg(args, uint64_t*); 649 | unpack_uint64_t(&bp, Q, *ep); 650 | END_REPETITION(); 651 | break; 652 | case 'f': 653 | BEGIN_REPETITION(); 654 | f = va_arg(args, float*); 655 | unpack_float(&bp, f, *ep); 656 | END_REPETITION(); 657 | break; 658 | case 'd': 659 | BEGIN_REPETITION(); 660 | d = va_arg(args, double*); 661 | unpack_double(&bp, d, *ep); 662 | END_REPETITION(); 663 | break; 664 | case 's': /* fall through */ 665 | case 'p': 666 | { 667 | int i = 0; 668 | s = va_arg(args, char*); 669 | BEGIN_REPETITION(); 670 | s[i++] = *bp++; 671 | END_REPETITION(); 672 | } 673 | break; 674 | case 'x': 675 | BEGIN_REPETITION(); 676 | bp++; 677 | END_REPETITION(); 678 | break; 679 | case 'v': 680 | BEGIN_REPETITION(); 681 | v = va_arg(args, int64_t*); 682 | unpack_signed_varint(&bp, v, *ep); 683 | END_REPETITION(); 684 | break; 685 | case 'V': 686 | BEGIN_REPETITION(); 687 | V = va_arg(args, uint64_t*); 688 | unpack_varint(&bp, V, *ep); 689 | END_REPETITION(); 690 | break; 691 | default: 692 | if (isdigit((int)*p)) { 693 | INC_REPETITION(); 694 | } else { 695 | return -1; 696 | } 697 | } 698 | 699 | if (!isdigit((int)*p)) { 700 | CLEAR_REPETITION(); 701 | } 702 | } 703 | return (bp - buf); 704 | } 705 | 706 | /* 707 | * EXPORT 708 | * 709 | * preifx: struct_ 710 | * 711 | */ 712 | int struct_pack(void *buf, const char *fmt, ...) 713 | { 714 | va_list args; 715 | int packed_len = 0; 716 | 717 | va_start(args, fmt); 718 | packed_len = pack_va_list( 719 | (unsigned char*)buf, 0, fmt, args); 720 | va_end(args); 721 | 722 | return packed_len; 723 | } 724 | 725 | int struct_pack_into(int offset, void *buf, const char *fmt, ...) 726 | { 727 | va_list args; 728 | int packed_len = 0; 729 | 730 | va_start(args, fmt); 731 | packed_len = pack_va_list( 732 | (unsigned char*)buf, offset, fmt, args); 733 | va_end(args); 734 | 735 | return packed_len; 736 | } 737 | 738 | int struct_unpack(const void *buf, const char *fmt, ...) 739 | { 740 | va_list args; 741 | int unpacked_len = 0; 742 | 743 | va_start(args, fmt); 744 | unpacked_len = unpack_va_list( 745 | (const unsigned char*)buf, 0, fmt, args); 746 | va_end(args); 747 | 748 | return unpacked_len; 749 | } 750 | 751 | int struct_unpack_from(int offset, const void *buf, const char *fmt, ...) 752 | { 753 | va_list args; 754 | int unpacked_len = 0; 755 | 756 | va_start(args, fmt); 757 | unpacked_len = unpack_va_list( 758 | (const unsigned char*)buf, offset, fmt, args); 759 | va_end(args); 760 | 761 | return unpacked_len; 762 | } 763 | 764 | int struct_calcsize(const char *fmt) 765 | { 766 | INIT_REPETITION(); 767 | int ret = 0; 768 | const char *p; 769 | 770 | if (STRUCT_ENDIAN_NOT_SET == myendian) { 771 | struct_init(); 772 | } 773 | 774 | for (p = fmt; *p != '\0'; p++) { 775 | switch (*p) { 776 | case '=': /* fall through */ 777 | case '<': /* fall through */ 778 | case '>': /* fall through */ 779 | case '!': /* ignore endian characters */ 780 | break; 781 | case 'b': 782 | BEGIN_REPETITION(); 783 | ret += sizeof(int8_t); 784 | END_REPETITION(); 785 | break; 786 | case 'B': 787 | BEGIN_REPETITION(); 788 | ret += sizeof(uint8_t); 789 | END_REPETITION(); 790 | break; 791 | case 'h': 792 | BEGIN_REPETITION(); 793 | ret += sizeof(int16_t); 794 | END_REPETITION(); 795 | break; 796 | case 'H': 797 | BEGIN_REPETITION(); 798 | ret += sizeof(uint16_t); 799 | END_REPETITION(); 800 | break; 801 | case 'i': /* fall through */ 802 | case 'l': 803 | BEGIN_REPETITION(); 804 | ret += sizeof(int32_t); 805 | END_REPETITION(); 806 | break; 807 | case 'I': /* fall through */ 808 | case 'L': 809 | BEGIN_REPETITION(); 810 | ret += sizeof(uint32_t); 811 | END_REPETITION(); 812 | break; 813 | case 'q': 814 | BEGIN_REPETITION(); 815 | ret += sizeof(int64_t); 816 | END_REPETITION(); 817 | break; 818 | case 'Q': 819 | BEGIN_REPETITION(); 820 | ret += sizeof(uint64_t); 821 | END_REPETITION(); 822 | break; 823 | case 'f': 824 | BEGIN_REPETITION(); 825 | ret += sizeof(int32_t); // see pack_float() 826 | END_REPETITION(); 827 | break; 828 | case 'd': 829 | BEGIN_REPETITION(); 830 | ret += sizeof(int64_t); // see pack_double() 831 | END_REPETITION(); 832 | break; 833 | case 's': /* fall through */ 834 | case 'p': 835 | BEGIN_REPETITION(); 836 | ret += sizeof(int8_t); 837 | END_REPETITION(); 838 | break; 839 | case 'x': 840 | BEGIN_REPETITION(); 841 | ret += sizeof(int8_t); 842 | END_REPETITION(); 843 | break; 844 | case 'v': 845 | BEGIN_REPETITION(); 846 | ret += 10; 847 | END_REPETITION(); 848 | break; 849 | case 'V': 850 | BEGIN_REPETITION(); 851 | ret += 10; 852 | END_REPETITION(); 853 | break; 854 | default: 855 | if (isdigit((int)*p)) { 856 | INC_REPETITION(); 857 | } else { 858 | return -1; 859 | } 860 | } 861 | 862 | if (!isdigit((int)*p)) { 863 | CLEAR_REPETITION(); 864 | } 865 | } 866 | return ret; 867 | } 868 | -------------------------------------------------------------------------------- /test/struct_test.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * struct_test.cpp 3 | * 4 | * Created on: 2011. 5. 6. 5 | * Author: wonseok choi 6 | */ 7 | 8 | #include "struct.h" 9 | #include "gtest/gtest.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | namespace { 19 | 20 | class Struct:public ::testing::Test { 21 | protected: 22 | Struct() {} 23 | virtual ~Struct() {} 24 | 25 | virtual void SetUp() 26 | { 27 | memset(buf, 0, sizeof(buf)); 28 | } 29 | 30 | virtual void TearDown() {} 31 | 32 | unsigned char buf[BUFSIZ]; 33 | static const char sc; 34 | static const unsigned char uc; 35 | }; 36 | 37 | const char Struct::sc = -42; 38 | const unsigned char Struct::uc = 42; 39 | 40 | TEST_F(Struct, memcpyCompatibilityValid) 41 | { 42 | int16_t i = 0x1234; 43 | char mbuf[sizeof(int16_t)]; 44 | 45 | struct_pack(buf, "h", i); 46 | memcpy(mbuf, &i, sizeof(int16_t)); 47 | 48 | EXPECT_EQ(buf[0], mbuf[0]); 49 | EXPECT_EQ(buf[1], mbuf[1]); 50 | } 51 | 52 | TEST_F(Struct, CalcsizeValid) 53 | { 54 | char strbuf[32]; 55 | 56 | EXPECT_TRUE(sizeof(char) == struct_calcsize("b")); 57 | EXPECT_TRUE(sizeof(unsigned char) == struct_calcsize("B")); 58 | EXPECT_TRUE(sizeof(int16_t) == struct_calcsize("h")); 59 | EXPECT_TRUE(sizeof(uint16_t) == struct_calcsize("H")); 60 | EXPECT_TRUE(sizeof(int32_t) == struct_calcsize("l")); 61 | EXPECT_TRUE(sizeof(uint32_t) == struct_calcsize("L")); 62 | EXPECT_TRUE(sizeof(int32_t) == struct_calcsize("i")); 63 | EXPECT_TRUE(sizeof(uint32_t) == struct_calcsize("I")); 64 | EXPECT_TRUE(sizeof(int64_t) == struct_calcsize("q")); 65 | EXPECT_TRUE(sizeof(uint64_t) == struct_calcsize("Q")); 66 | EXPECT_TRUE(sizeof(float) == struct_calcsize("f")); 67 | EXPECT_TRUE(sizeof(double) == struct_calcsize("d")); 68 | EXPECT_TRUE(sizeof(strbuf) == struct_calcsize("32s")); 69 | EXPECT_TRUE(sizeof(strbuf) == struct_calcsize("32p")); 70 | EXPECT_TRUE(sizeof(char) == struct_calcsize("x")); 71 | EXPECT_TRUE(10 == struct_calcsize("v")); 72 | EXPECT_TRUE(10 == struct_calcsize("V")); 73 | } 74 | 75 | TEST_F(Struct, PadBytePackUnpackingValid1) 76 | { 77 | char o1, o2; 78 | struct_pack(buf, "2x2b", sc, sc); 79 | struct_unpack(buf, "2x2b", &o1, &o2); 80 | EXPECT_EQ(sc, o1); 81 | EXPECT_EQ(sc, o2); 82 | } 83 | 84 | TEST_F(Struct, PadBytePackUnpackingValid2) 85 | { 86 | char o1, o2; 87 | struct_pack(buf, "xbxb", sc, sc); 88 | struct_unpack(buf, "xbxb", &o1, &o2); 89 | EXPECT_EQ(sc, o1); 90 | EXPECT_EQ(sc, o2); 91 | } 92 | 93 | TEST_F(Struct, Signed1bytePackUnpackingValid) 94 | { 95 | char o; 96 | struct_pack(buf, "b", sc); 97 | struct_unpack(buf, "b", &o); 98 | EXPECT_EQ(sc, o); 99 | } 100 | 101 | TEST_F(Struct, SignedMultiBytePackUnpackingValid) 102 | { 103 | char o1, o2, o3, o4; 104 | struct_pack(buf, "4b", sc, sc, sc, sc); 105 | struct_unpack(buf, "4b", &o1, &o2, &o3, &o4); 106 | EXPECT_EQ(sc, o1); 107 | EXPECT_EQ(sc, o2); 108 | EXPECT_EQ(sc, o3); 109 | EXPECT_EQ(sc, o4); 110 | } 111 | 112 | TEST_F(Struct, Signed1BytePackUnpackingWithOffsetValid) 113 | { 114 | char o; 115 | struct_pack_into(1, buf, "b", sc); 116 | struct_unpack_from(1, buf, "b", &o); 117 | EXPECT_EQ(sc, o); 118 | } 119 | 120 | TEST_F(Struct, SignedMultiBytePackUnpackingWithOffsetValid) 121 | { 122 | char o1, o2, o3, o4; 123 | struct_pack_into(1, buf, "4b", sc, sc, sc, sc); 124 | struct_unpack_from(1, buf, "4b", &o1, &o2, &o3, &o4); 125 | EXPECT_EQ(sc, o1); 126 | EXPECT_EQ(sc, o2); 127 | EXPECT_EQ(sc, o3); 128 | EXPECT_EQ(sc, o4); 129 | } 130 | 131 | TEST_F(Struct, SingleBytePackUnpackingValid) 132 | { 133 | unsigned char o; 134 | struct_pack(buf, "B", uc); 135 | struct_unpack(buf, "B", &o); 136 | EXPECT_EQ(uc, o); 137 | } 138 | 139 | TEST_F(Struct, MultiBytePackUnpackingValid) 140 | { 141 | unsigned char o1, o2, o3, o4; 142 | struct_pack(buf, "4B", uc, uc, uc, uc); 143 | struct_unpack(buf, "4B", &o1, &o2, &o3, &o4); 144 | EXPECT_EQ(uc, o1); 145 | EXPECT_EQ(uc, o2); 146 | EXPECT_EQ(uc, o3); 147 | EXPECT_EQ(uc, o4); 148 | } 149 | 150 | TEST_F(Struct, SingleBytePackUnpackingWithOffsetValid) 151 | { 152 | unsigned char o; 153 | struct_pack_into(1, buf, "B", uc); 154 | struct_unpack_from(1, buf, "B", &o); 155 | EXPECT_EQ(uc, o); 156 | } 157 | 158 | TEST_F(Struct, MultiBytePackUnpackingWithOffsetValid) 159 | { 160 | unsigned char o1, o2, o3, o4; 161 | struct_pack_into(1, buf, "4B", uc, uc, uc, uc); 162 | struct_unpack_from(1, buf, "4B", &o1, &o2, &o3, &o4); 163 | EXPECT_EQ(uc, o1); 164 | EXPECT_EQ(uc, o2); 165 | EXPECT_EQ(uc, o3); 166 | EXPECT_EQ(uc, o4); 167 | } 168 | 169 | TEST_F(Struct, int16_tPackUnpackingValid) 170 | { 171 | int16_t i = 0x1234; 172 | int16_t o; 173 | struct_pack(buf, "h", i); 174 | struct_unpack(buf, "h", &o); 175 | EXPECT_EQ(i, o); 176 | } 177 | 178 | TEST_F(Struct, int16_tLimitMinPackUnpackingValid) 179 | { 180 | int16_t i = std::numeric_limits::min(); 181 | int16_t o; 182 | struct_pack(buf, "h", i); 183 | struct_unpack(buf, "h", &o); 184 | EXPECT_EQ(i, o); 185 | } 186 | 187 | TEST_F(Struct, int16_tLimitMaxPackUnpackingValid) 188 | { 189 | int16_t i = std::numeric_limits::max(); 190 | int16_t o; 191 | struct_pack(buf, "h", i); 192 | struct_unpack(buf, "h", &o); 193 | EXPECT_EQ(i, o); 194 | } 195 | 196 | TEST_F(Struct, int16_tNegPackUnpackingValid) 197 | { 198 | int16_t i = -1234; 199 | int16_t o; 200 | struct_pack(buf, "h", i); 201 | struct_unpack(buf, "h", &o); 202 | EXPECT_EQ(i, o); 203 | } 204 | 205 | TEST_F(Struct, int16_tMultiPackUnpackingValid) 206 | { 207 | int16_t i = 0x1234; 208 | int16_t o1, o2; 209 | struct_pack(buf, "2h", i, i); 210 | struct_unpack(buf, "2h", &o1, &o2); 211 | EXPECT_EQ(i, o1); 212 | EXPECT_EQ(i, o2); 213 | } 214 | 215 | TEST_F(Struct, int16_tPackUnpackingWithOffsetValid) 216 | { 217 | int16_t i = 0x1234; 218 | int16_t o; 219 | struct_pack_into(1, buf, "h", i); 220 | struct_unpack_from(1, buf, "h", &o); 221 | EXPECT_EQ(i, o); 222 | } 223 | 224 | TEST_F(Struct, int16_tMultiPackUnpackingWithOffsetValid) 225 | { 226 | int16_t i = 0x1234; 227 | int16_t o1, o2; 228 | struct_pack_into(1, buf, "2h", i, i); 229 | struct_unpack_from(1, buf, "2h", &o1, &o2); 230 | EXPECT_EQ(i, o1); 231 | EXPECT_EQ(i, o2); 232 | } 233 | 234 | TEST_F(Struct, uint16_tPackUnpackingValid) 235 | { 236 | uint16_t i = 0x1234; 237 | uint16_t o; 238 | struct_pack(buf, "H", i); 239 | struct_unpack(buf, "H", &o); 240 | EXPECT_EQ(i, o); 241 | } 242 | 243 | TEST_F(Struct, uint16_tLimitMinPackUnpackingValid) 244 | { 245 | uint16_t i = std::numeric_limits::min(); 246 | uint16_t o; 247 | struct_pack(buf, "H", i); 248 | struct_unpack(buf, "H", &o); 249 | EXPECT_EQ(i, o); 250 | } 251 | 252 | TEST_F(Struct, uint16_tLimitMaxPackUnpackingValid) 253 | { 254 | uint16_t i = std::numeric_limits::max(); 255 | uint16_t o; 256 | struct_pack(buf, "H", i); 257 | struct_unpack(buf, "H", &o); 258 | EXPECT_EQ(i, o); 259 | } 260 | 261 | TEST_F(Struct, uint16_tMultiPackUnpackingValid) 262 | { 263 | uint16_t i = 0x1234; 264 | uint16_t o1, o2; 265 | struct_pack(buf, "2H", i, i); 266 | struct_unpack(buf, "2H", &o1, &o2); 267 | EXPECT_EQ(i, o1); 268 | EXPECT_EQ(i, o2); 269 | } 270 | 271 | TEST_F(Struct, uint16_tPackUnpackingWithOffsetValid) 272 | { 273 | uint16_t i = 0x1234; 274 | uint16_t o; 275 | struct_pack_into(1, buf, "H", i); 276 | struct_unpack_from(1, buf, "H", &o); 277 | EXPECT_EQ(i, o); 278 | } 279 | 280 | TEST_F(Struct, uint16_tMultiPackUnpackingWithOffsetValid) 281 | { 282 | uint16_t i = 0x1234; 283 | uint16_t o1, o2; 284 | struct_pack_into(1, buf, "2H", i, i); 285 | struct_unpack_from(1, buf, "2H", &o1, &o2); 286 | EXPECT_EQ(i, o1); 287 | EXPECT_EQ(i, o2); 288 | } 289 | 290 | TEST_F(Struct, int32_t_i_PackUnpackingValid) 291 | { 292 | int32_t i = 0x12345678; 293 | int32_t o; 294 | struct_pack(buf, "i", i); 295 | struct_unpack(buf, "i", &o); 296 | EXPECT_EQ(i, o); 297 | } 298 | 299 | TEST_F(Struct, int32_t_i_LimitMinPackUnpackingValid) 300 | { 301 | int32_t i = std::numeric_limits::min(); 302 | int32_t o; 303 | struct_pack(buf, "i", i); 304 | struct_unpack(buf, "i", &o); 305 | EXPECT_EQ(i, o); 306 | } 307 | 308 | TEST_F(Struct, int32_t_i_LimitMaxPackUnpackingValid) 309 | { 310 | int32_t i = std::numeric_limits::max(); 311 | int32_t o; 312 | struct_pack(buf, "i", i); 313 | struct_unpack(buf, "i", &o); 314 | EXPECT_EQ(i, o); 315 | } 316 | 317 | TEST_F(Struct, int32_t_i_NegPackUnpackingValid) 318 | { 319 | int32_t i = -12345678; 320 | int32_t o; 321 | struct_pack(buf, "i", i); 322 | struct_unpack(buf, "i", &o); 323 | EXPECT_EQ(i, o); 324 | } 325 | 326 | TEST_F(Struct, int32_t_i_MultiPackUnpackingValid) 327 | { 328 | int32_t i = 0x12345678; 329 | int32_t o1, o2; 330 | struct_pack(buf, "2i", i, i); 331 | struct_unpack(buf, "2i", &o1, &o2); 332 | EXPECT_EQ(i, o1); 333 | EXPECT_EQ(i, o2); 334 | } 335 | 336 | TEST_F(Struct, int32_t_i_PackUnpackingWithOffsetValid) 337 | { 338 | int32_t i = 0x12345678; 339 | int32_t o; 340 | struct_pack_into(1, buf, "i", i); 341 | struct_unpack_from(1, buf, "i", &o); 342 | EXPECT_EQ(i, o); 343 | } 344 | 345 | TEST_F(Struct, int32_t_i_MultiPackUnpackingWithOffsetValid) 346 | { 347 | int32_t i = 0x12345678; 348 | int32_t o1, o2; 349 | struct_pack_into(1, buf, "2i", i, i); 350 | struct_unpack_from(1, buf, "2i", &o1, &o2); 351 | EXPECT_EQ(i, o1); 352 | EXPECT_EQ(i, o2); 353 | } 354 | 355 | TEST_F(Struct, uint32_t_I_PackUnpackingValid) 356 | { 357 | uint32_t i = 0x12345678; 358 | uint32_t o; 359 | struct_pack(buf, "I", i); 360 | struct_unpack(buf, "I", &o); 361 | EXPECT_EQ(i, o); 362 | } 363 | 364 | TEST_F(Struct, uint32_t_I_LimitMinPackUnpackingValid) 365 | { 366 | uint32_t i = std::numeric_limits::min(); 367 | uint32_t o; 368 | struct_pack(buf, "I", i); 369 | struct_unpack(buf, "I", &o); 370 | EXPECT_EQ(i, o); 371 | } 372 | 373 | TEST_F(Struct, uint32_t_I_LimitMaxPackUnpackingValid) 374 | { 375 | uint32_t i = std::numeric_limits::max(); 376 | uint32_t o; 377 | struct_pack(buf, "I", i); 378 | struct_unpack(buf, "I", &o); 379 | EXPECT_EQ(i, o); 380 | } 381 | 382 | TEST_F(Struct, uint32_t_I_MultiPackUnpackingValid) 383 | { 384 | uint32_t i = 0x12345678; 385 | uint32_t o1, o2; 386 | struct_pack(buf, "2I", i, i); 387 | struct_unpack(buf, "2I", &o1, &o2); 388 | EXPECT_EQ(i, o1); 389 | EXPECT_EQ(i, o2); 390 | } 391 | 392 | TEST_F(Struct, uint32_t_I_PackUnpackingWithOffsetValid) 393 | { 394 | uint32_t i = 0x12345678; 395 | uint32_t o; 396 | struct_pack_into(1, buf, "I", i); 397 | struct_unpack_from(1, buf, "I", &o); 398 | EXPECT_EQ(i, o); 399 | } 400 | 401 | TEST_F(Struct, uint32_t_I_MultiPackUnpackingWithOffsetValid) 402 | { 403 | uint32_t i = 0x12345678; 404 | uint32_t o1, o2; 405 | struct_pack_into(1, buf, "2I", i, i); 406 | struct_unpack_from(1, buf, "2I", &o1, &o2); 407 | EXPECT_EQ(i, o1); 408 | EXPECT_EQ(i, o2); 409 | } 410 | 411 | TEST_F(Struct, int32_t_l_PackUnpackingValid) 412 | { 413 | int32_t i = 0x12345678; 414 | int32_t o; 415 | struct_pack(buf, "l", i); 416 | struct_unpack(buf, "l", &o); 417 | EXPECT_EQ(i, o); 418 | } 419 | 420 | TEST_F(Struct, int32_t_l_LimitMinPackUnpackingValid) 421 | { 422 | int32_t i = std::numeric_limits::min(); 423 | int32_t o; 424 | struct_pack(buf, "l", i); 425 | struct_unpack(buf, "l", &o); 426 | EXPECT_EQ(i, o); 427 | } 428 | 429 | TEST_F(Struct, int32_t_l_LimitMaxPackUnpackingValid) 430 | { 431 | int32_t i = std::numeric_limits::max(); 432 | int32_t o; 433 | struct_pack(buf, "l", i); 434 | struct_unpack(buf, "l", &o); 435 | EXPECT_EQ(i, o); 436 | } 437 | 438 | TEST_F(Struct, int32_t_l_NegPackUnpackingValid) 439 | { 440 | int32_t i = -12345678; 441 | int32_t o; 442 | struct_pack(buf, "l", i); 443 | struct_unpack(buf, "l", &o); 444 | EXPECT_EQ(i, o); 445 | } 446 | 447 | TEST_F(Struct, int32_t_l_MultiPackUnpackingValid) 448 | { 449 | int32_t i = 0x12345678; 450 | int32_t o1, o2; 451 | struct_pack(buf, "2l", i, i); 452 | struct_unpack(buf, "2l", &o1, &o2); 453 | EXPECT_EQ(i, o1); 454 | EXPECT_EQ(i, o2); 455 | } 456 | 457 | TEST_F(Struct, int32_t_l_PackUnpackingWithOffsetValid) 458 | { 459 | int32_t i = 0x12345678; 460 | int32_t o; 461 | struct_pack_into(1, buf, "l", i); 462 | struct_unpack_from(1, buf, "l", &o); 463 | EXPECT_EQ(i, o); 464 | } 465 | 466 | TEST_F(Struct, int32_t_l_MultiPackUnpackingWithOffsetValid) 467 | { 468 | int32_t i = 0x12345678; 469 | int32_t o1, o2; 470 | struct_pack_into(1, buf, "2l", i, i); 471 | struct_unpack_from(1, buf, "2l", &o1, &o2); 472 | EXPECT_EQ(i, o1); 473 | EXPECT_EQ(i, o2); 474 | } 475 | 476 | TEST_F(Struct, uint32_t_L_PackUnpackingValid) 477 | { 478 | uint32_t i = 0x12345678; 479 | uint32_t o; 480 | struct_pack(buf, "L", i); 481 | struct_unpack(buf, "L", &o); 482 | EXPECT_EQ(i, o); 483 | } 484 | 485 | TEST_F(Struct, uint32_t_L_LimitMinPackUnpackingValid) 486 | { 487 | uint32_t i = std::numeric_limits::min(); 488 | uint32_t o; 489 | struct_pack(buf, "L", i); 490 | struct_unpack(buf, "L", &o); 491 | EXPECT_EQ(i, o); 492 | } 493 | 494 | TEST_F(Struct, uint32_t_L_LimitMaxPackUnpackingValid) 495 | { 496 | uint32_t i = std::numeric_limits::max(); 497 | uint32_t o; 498 | struct_pack(buf, "L", i); 499 | struct_unpack(buf, "L", &o); 500 | EXPECT_EQ(i, o); 501 | } 502 | 503 | TEST_F(Struct, uint32_t_L_MultiPackUnpackingValid) 504 | { 505 | uint32_t i = 0x12345678; 506 | uint32_t o1, o2; 507 | struct_pack(buf, "2L", i, i); 508 | struct_unpack(buf, "2L", &o1, &o2); 509 | EXPECT_EQ(i, o1); 510 | EXPECT_EQ(i, o2); 511 | } 512 | 513 | TEST_F(Struct, uint32_t_L_PackUnpackingWithOffsetValid) 514 | { 515 | uint32_t i = 0x12345678; 516 | uint32_t o; 517 | struct_pack_into(1, buf, "L", i); 518 | struct_unpack_from(1, buf, "L", &o); 519 | EXPECT_EQ(i, o); 520 | } 521 | 522 | TEST_F(Struct, uint32_t_L_MultiPackUnpackingWithOffsetValid) 523 | { 524 | uint32_t i = 0x12345678; 525 | uint32_t o1, o2; 526 | struct_pack_into(1, buf, "2L", i, i); 527 | struct_unpack_from(1, buf, "2L", &o1, &o2); 528 | EXPECT_EQ(i, o1); 529 | EXPECT_EQ(i, o2); 530 | } 531 | 532 | TEST_F(Struct, int64_tPackUnpackingValid) 533 | { 534 | int64_t i = 0x1234567887654321LL; 535 | int64_t o; 536 | struct_pack(buf, "q", i); 537 | struct_unpack(buf, "q", &o); 538 | EXPECT_EQ(i, o); 539 | } 540 | 541 | TEST_F(Struct, int64_t_LimitMinPackUnpackingValid) 542 | { 543 | int64_t i = std::numeric_limits::min(); 544 | int64_t o; 545 | struct_pack(buf, "q", i); 546 | struct_unpack(buf, "q", &o); 547 | EXPECT_EQ(i, o); 548 | } 549 | 550 | TEST_F(Struct, int64_t_LimitMaxPackUnpackingValid) 551 | { 552 | int64_t i = std::numeric_limits::max(); 553 | int64_t o; 554 | struct_pack(buf, "q", i); 555 | struct_unpack(buf, "q", &o); 556 | EXPECT_EQ(i, o); 557 | } 558 | 559 | TEST_F(Struct, int64_tNegPackUnpackingValid) 560 | { 561 | int64_t i = -1234567887654321; 562 | int64_t o; 563 | struct_pack(buf, "q", i); 564 | struct_unpack(buf, "q", &o); 565 | EXPECT_EQ(i, o); 566 | } 567 | 568 | TEST_F(Struct, int64_tMultiPackUnpackingValid) 569 | { 570 | int64_t i = 0x1234567887654321LL; 571 | int64_t o1, o2; 572 | struct_pack(buf, "2q", i, i); 573 | struct_unpack(buf, "2q", &o1, &o2); 574 | EXPECT_EQ(i, o1); 575 | EXPECT_EQ(i, o2); 576 | } 577 | 578 | TEST_F(Struct, int64_tPackUnpackingWithOffsetValid) 579 | { 580 | int64_t i = 0x1234567887654321LL; 581 | int64_t o; 582 | struct_pack_into(1, buf, "q", i); 583 | struct_unpack_from(1, buf, "q", &o); 584 | EXPECT_EQ(i, o); 585 | } 586 | 587 | TEST_F(Struct, int64_t_MultiPackUnpackingWithOffsetValid) 588 | { 589 | int64_t i = 0x1234567887654321LL; 590 | int64_t o1, o2; 591 | struct_pack_into(1, buf, "2q", i, i); 592 | struct_unpack_from(1, buf, "2q", &o1, &o2); 593 | EXPECT_EQ(i, o1); 594 | EXPECT_EQ(i, o2); 595 | } 596 | 597 | TEST_F(Struct, uint64_tPackUnpackingValid) 598 | { 599 | uint64_t i = 0x1234567887654321LL; 600 | uint64_t o; 601 | struct_pack(buf, "Q", i); 602 | struct_unpack(buf, "Q", &o); 603 | EXPECT_EQ(i, o); 604 | } 605 | 606 | TEST_F(Struct, uint64_t_LimitMinPackUnpackingValid) 607 | { 608 | uint64_t i = std::numeric_limits::min(); 609 | uint64_t o; 610 | struct_pack(buf, "Q", i); 611 | struct_unpack(buf, "Q", &o); 612 | EXPECT_EQ(i, o); 613 | } 614 | 615 | TEST_F(Struct, uint64_t_LimitMaxPackUnpackingValid) 616 | { 617 | uint64_t i = std::numeric_limits::max(); 618 | uint64_t o; 619 | struct_pack(buf, "Q", i); 620 | struct_unpack(buf, "Q", &o); 621 | EXPECT_EQ(i, o); 622 | } 623 | 624 | TEST_F(Struct, uint64_tMultiPackUnpackingValid) 625 | { 626 | uint64_t i = 0x1234567887654321LL; 627 | uint64_t o1, o2; 628 | struct_pack(buf, "2Q", i, i); 629 | struct_unpack(buf, "2Q", &o1, &o2); 630 | EXPECT_EQ(i, o1); 631 | EXPECT_EQ(i, o2); 632 | } 633 | 634 | TEST_F(Struct, uint64_tPackUnpackingWithOffsetValid) 635 | { 636 | uint64_t i = 0x1234567887654321LL; 637 | uint64_t o; 638 | struct_pack_into(1, buf, "Q", i); 639 | struct_unpack_from(1, buf, "Q", &o); 640 | EXPECT_EQ(i, o); 641 | } 642 | 643 | TEST_F(Struct, uint64_t_MultiPackUnpackingWithOffsetValid) 644 | { 645 | uint64_t i = 0x1234567887654321LL; 646 | uint64_t o1, o2; 647 | struct_pack_into(1, buf, "2Q", i, i); 648 | struct_unpack_from(1, buf, "2Q", &o1, &o2); 649 | EXPECT_EQ(i, o1); 650 | EXPECT_EQ(i, o2); 651 | } 652 | 653 | TEST_F(Struct, floatPackUnpackingValid) 654 | { 655 | float i = 3.141592; 656 | float o; 657 | struct_pack(buf, "f", i); 658 | struct_unpack(buf, "f", &o); 659 | EXPECT_DOUBLE_EQ(i, o); 660 | } 661 | 662 | TEST_F(Struct, floatNegPackUnpackingValid) 663 | { 664 | float i = -3.141592; 665 | float o; 666 | struct_pack(buf, "f", i); 667 | struct_unpack(buf, "f", &o); 668 | EXPECT_DOUBLE_EQ(i, o); 669 | } 670 | 671 | TEST_F(Struct, floatMultiPackUnpackingValid) 672 | { 673 | float i = 3.141592; 674 | float o1, o2; 675 | struct_pack(buf, "2f", i, i); 676 | struct_unpack(buf, "2f", &o1, &o2); 677 | EXPECT_DOUBLE_EQ(i, o1); 678 | EXPECT_DOUBLE_EQ(i, o2); 679 | } 680 | 681 | TEST_F(Struct, floatPackUnpackingWithOffsetValid) 682 | { 683 | float i = 3.141592; 684 | float o; 685 | struct_pack_into(1, buf, "f", i); 686 | struct_unpack_from(1, buf, "f", &o); 687 | EXPECT_DOUBLE_EQ(i, o); 688 | } 689 | 690 | TEST_F(Struct, floatMultiPackUnpackingWithOffsetValid) 691 | { 692 | float i = 3.141592; 693 | float o1, o2; 694 | struct_pack_into(1, buf, "2f", i, i); 695 | struct_unpack_from(1, buf, "2f", &o1, &o2); 696 | EXPECT_DOUBLE_EQ(i, o1); 697 | EXPECT_DOUBLE_EQ(i, o2); 698 | } 699 | 700 | TEST_F(Struct, doublePackUnpackingValid) 701 | { 702 | double i = 3.141592; 703 | double o; 704 | struct_pack(buf, "d", i); 705 | struct_unpack(buf, "d", &o); 706 | EXPECT_DOUBLE_EQ(i, o); 707 | } 708 | 709 | TEST_F(Struct, doubleNegPackUnpackingValid) 710 | { 711 | double i = -3.141592; 712 | double o; 713 | struct_pack(buf, "d", i); 714 | struct_unpack(buf, "d", &o); 715 | EXPECT_DOUBLE_EQ(i, o); 716 | } 717 | 718 | TEST_F(Struct, doubleMultiPackUnpackingValid) 719 | { 720 | double i = 3.141592; 721 | double o1, o2; 722 | struct_pack(buf, "2d", i, i); 723 | struct_unpack(buf, "2d", &o1, &o2); 724 | EXPECT_DOUBLE_EQ(i, o1); 725 | EXPECT_DOUBLE_EQ(i, o2); 726 | } 727 | 728 | TEST_F(Struct, doublePackUnpackingWithOffsetValid) 729 | { 730 | double i = 3.141592; 731 | double o; 732 | struct_pack_into(1, buf, "d", i); 733 | struct_unpack_from(1, buf, "d", &o); 734 | EXPECT_DOUBLE_EQ(i, o); 735 | } 736 | 737 | TEST_F(Struct, doubleMultiPackUnpackingWithOffsetValid) 738 | { 739 | double i = 3.141592; 740 | double o1, o2; 741 | struct_pack_into(1, buf, "2d", i, i); 742 | struct_unpack_from(1, buf, "2d", &o1, &o2); 743 | EXPECT_DOUBLE_EQ(i, o1); 744 | EXPECT_DOUBLE_EQ(i, o2); 745 | } 746 | 747 | TEST_F(Struct, StringPackUnpackingValidWithS) 748 | { 749 | char str[32]; 750 | char o[32]; 751 | char fmt[32]; 752 | 753 | memset(str, 0, sizeof(str)); 754 | memset(o, 0, sizeof(o)); 755 | memset(fmt, 0, sizeof(fmt)); 756 | strcpy(str, "test0"); 757 | sprintf(fmt, "%ds", (int)strlen(str)); 758 | 759 | struct_pack(buf, fmt, str); 760 | struct_unpack(buf, fmt, o); 761 | EXPECT_STREQ(str, o); 762 | } 763 | 764 | TEST_F(Struct, StringPackUnpackingValidWithP) 765 | { 766 | char str[32]; 767 | char o[32]; 768 | char fmt[32]; 769 | 770 | memset(str, 0, sizeof(str)); 771 | memset(o, 0, sizeof(o)); 772 | memset(fmt, 0, sizeof(fmt)); 773 | strcpy(str, "test0"); 774 | sprintf(fmt, "%dp", (int)strlen(str)); 775 | 776 | struct_pack(buf, fmt, str); 777 | struct_unpack(buf, fmt, o); 778 | EXPECT_STREQ(str, o); 779 | } 780 | 781 | TEST_F(Struct, StringMultiPackUnpackingValid) 782 | { 783 | char str1[32]; 784 | char str2[32]; 785 | char o1[32]; 786 | char o2[32]; 787 | char fmt[32]; 788 | 789 | memset(str1, 0, sizeof(str1)); 790 | memset(str2, 0, sizeof(str2)); 791 | memset(o1, 0, sizeof(o1)); 792 | memset(o2, 0, sizeof(o2)); 793 | memset(fmt, 0, sizeof(fmt)); 794 | strcpy(str1, "test0"); 795 | strcpy(str2, "test1"); 796 | sprintf(fmt, "%ds%ds", (int)strlen(str1), (int)strlen(str2)); 797 | 798 | struct_pack(buf, fmt, str1, str2); 799 | struct_unpack(buf, fmt, o1, o2); 800 | EXPECT_STREQ(str1, o1); 801 | EXPECT_STREQ(str2, o2); 802 | } 803 | 804 | TEST_F(Struct, int16_t_big_PackUnpackingValid) 805 | { 806 | int16_t i = 0x1234; 807 | int16_t o; 808 | struct_pack(buf, ">h", i); 809 | struct_unpack(buf, ">h", &o); 810 | EXPECT_EQ(i, o); 811 | } 812 | 813 | TEST_F(Struct, int16_t_big_MultiPackUnpackingValid) 814 | { 815 | int16_t i = 0x1234; 816 | int16_t o1, o2; 817 | struct_pack(buf, ">2h", i, i); 818 | struct_unpack(buf, ">2h", &o1, &o2); 819 | EXPECT_EQ(i, o1); 820 | EXPECT_EQ(i, o2); 821 | } 822 | 823 | TEST_F(Struct, int16_t_big_PackUnpackingWithOffsetValid) 824 | { 825 | int16_t i = 0x1234; 826 | int16_t o; 827 | struct_pack_into(1, buf, ">h", i); 828 | struct_unpack_from(1, buf, ">h", &o); 829 | EXPECT_EQ(i, o); 830 | } 831 | 832 | TEST_F(Struct, int16_t_big_MultiPackUnpackingWithOffsetValid) 833 | { 834 | int16_t i = 0x1234; 835 | int16_t o1, o2; 836 | struct_pack_into(1, buf, ">2h", i, i); 837 | struct_unpack_from(1, buf, ">2h", &o1, &o2); 838 | EXPECT_EQ(i, o1); 839 | EXPECT_EQ(i, o2); 840 | } 841 | 842 | TEST_F(Struct, uint16_t_big_PackUnpackingValid) 843 | { 844 | uint16_t i = 0x1234; 845 | uint16_t o; 846 | struct_pack(buf, ">H", i); 847 | struct_unpack(buf, ">H", &o); 848 | EXPECT_EQ(i, o); 849 | } 850 | 851 | TEST_F(Struct, uint16_t_big_MultiPackUnpackingValid) 852 | { 853 | uint16_t i = 0x1234; 854 | uint16_t o1, o2; 855 | struct_pack(buf, ">2H", i, i); 856 | struct_unpack(buf, ">2H", &o1, &o2); 857 | EXPECT_EQ(i, o1); 858 | EXPECT_EQ(i, o2); 859 | } 860 | 861 | TEST_F(Struct, uint16_t_big_PackUnpackingWithOffsetValid) 862 | { 863 | uint16_t i = 0x1234; 864 | uint16_t o; 865 | struct_pack_into(1, buf, ">H", i); 866 | struct_unpack_from(1, buf, ">H", &o); 867 | EXPECT_EQ(i, o); 868 | } 869 | 870 | TEST_F(Struct, uint16_t_big_MultiPackUnpackingWithOffsetValid) 871 | { 872 | uint16_t i = 0x1234; 873 | uint16_t o1, o2; 874 | struct_pack_into(1, buf, ">2H", i, i); 875 | struct_unpack_from(1, buf, ">2H", &o1, &o2); 876 | EXPECT_EQ(i, o1); 877 | EXPECT_EQ(i, o2); 878 | } 879 | 880 | TEST_F(Struct, int32_t_i_big_PackUnpackingValid) 881 | { 882 | int32_t i = 0x12345678; 883 | int32_t o; 884 | struct_pack(buf, ">i", i); 885 | struct_unpack(buf, ">i", &o); 886 | EXPECT_EQ(i, o); 887 | } 888 | 889 | TEST_F(Struct, int32_t_i_big_MultiPackUnpackingValid) 890 | { 891 | int32_t i = 0x12345678; 892 | int32_t o1, o2; 893 | struct_pack(buf, ">2i", i, i); 894 | struct_unpack(buf, ">2i", &o1, &o2); 895 | EXPECT_EQ(i, o1); 896 | EXPECT_EQ(i, o2); 897 | } 898 | 899 | TEST_F(Struct, int32_t_i_big_PackUnpackingWithOffsetValid) 900 | { 901 | int32_t i = 0x12345678; 902 | int32_t o; 903 | struct_pack_into(1, buf, ">i", i); 904 | struct_unpack_from(1, buf, ">i", &o); 905 | EXPECT_EQ(i, o); 906 | } 907 | 908 | TEST_F(Struct, int32_t_i_big_MultiPackUnpackingWithOffsetValid) 909 | { 910 | int32_t i = 0x12345678; 911 | int32_t o1, o2; 912 | struct_pack_into(1, buf, ">2i", i, i); 913 | struct_unpack_from(1, buf, ">2i", &o1, &o2); 914 | EXPECT_EQ(i, o1); 915 | EXPECT_EQ(i, o2); 916 | } 917 | 918 | TEST_F(Struct, uint32_t_I_big_PackUnpackingValid) 919 | { 920 | uint32_t i = 0x12345678; 921 | uint32_t o; 922 | struct_pack(buf, ">I", i); 923 | struct_unpack(buf, ">I", &o); 924 | EXPECT_EQ(i, o); 925 | } 926 | 927 | TEST_F(Struct, uint32_t_I_big_MultiPackUnpackingValid) 928 | { 929 | uint32_t i = 0x12345678; 930 | uint32_t o1, o2; 931 | struct_pack(buf, ">2I", i, i); 932 | struct_unpack(buf, ">2I", &o1, &o2); 933 | EXPECT_EQ(i, o1); 934 | EXPECT_EQ(i, o2); 935 | } 936 | 937 | TEST_F(Struct, uint32_t_I_big_PackUnpackingWithOffsetValid) 938 | { 939 | uint32_t i = 0x12345678; 940 | uint32_t o; 941 | struct_pack_into(1, buf, ">I", i); 942 | struct_unpack_from(1, buf, ">I", &o); 943 | EXPECT_EQ(i, o); 944 | } 945 | 946 | TEST_F(Struct, uint32_t_I_big_MultiPackUnpackingWithOffsetValid) 947 | { 948 | uint32_t i = 0x12345678; 949 | uint32_t o1, o2; 950 | struct_pack_into(1, buf, ">2I", i, i); 951 | struct_unpack_from(1, buf, ">2I", &o1, &o2); 952 | EXPECT_EQ(i, o1); 953 | EXPECT_EQ(i, o2); 954 | } 955 | 956 | TEST_F(Struct, int32_t_l_big_PackUnpackingValid) 957 | { 958 | int32_t i = 0x12345678; 959 | int32_t o; 960 | struct_pack(buf, ">l", i); 961 | struct_unpack(buf, ">l", &o); 962 | EXPECT_EQ(i, o); 963 | } 964 | 965 | TEST_F(Struct, int32_t_l_big_MultiPackUnpackingValid) 966 | { 967 | int32_t i = 0x12345678; 968 | int32_t o1, o2; 969 | struct_pack(buf, ">2l", i, i); 970 | struct_unpack(buf, ">2l", &o1, &o2); 971 | EXPECT_EQ(i, o1); 972 | EXPECT_EQ(i, o2); 973 | } 974 | 975 | TEST_F(Struct, int32_t_l_big_PackUnpackingWithOffsetValid) 976 | { 977 | int32_t i = 0x12345678; 978 | int32_t o; 979 | struct_pack_into(1, buf, ">l", i); 980 | struct_unpack_from(1, buf, ">l", &o); 981 | EXPECT_EQ(i, o); 982 | } 983 | 984 | TEST_F(Struct, int32_t_l_big_MultiPackUnpackingWithOffsetValid) 985 | { 986 | int32_t i = 0x12345678; 987 | int32_t o1, o2; 988 | struct_pack_into(1, buf, ">2l", i, i); 989 | struct_unpack_from(1, buf, ">2l", &o1, &o2); 990 | EXPECT_EQ(i, o1); 991 | EXPECT_EQ(i, o2); 992 | } 993 | 994 | TEST_F(Struct, uint32_t_L_big_PackUnpackingValid) 995 | { 996 | uint32_t i = 0x12345678; 997 | uint32_t o; 998 | struct_pack(buf, ">L", i); 999 | struct_unpack(buf, ">L", &o); 1000 | EXPECT_EQ(i, o); 1001 | } 1002 | 1003 | TEST_F(Struct, uint32_t_L_big_MultiPackUnpackingValid) 1004 | { 1005 | uint32_t i = 0x12345678; 1006 | uint32_t o1, o2; 1007 | struct_pack(buf, ">2L", i, i); 1008 | struct_unpack(buf, ">2L", &o1, &o2); 1009 | EXPECT_EQ(i, o1); 1010 | EXPECT_EQ(i, o2); 1011 | } 1012 | 1013 | TEST_F(Struct, uint32_t_L_big_PackUnpackingWithOffsetValid) 1014 | { 1015 | uint32_t i = 0x12345678; 1016 | uint32_t o; 1017 | struct_pack_into(1, buf, ">L", i); 1018 | struct_unpack_from(1, buf, ">L", &o); 1019 | EXPECT_EQ(i, o); 1020 | } 1021 | 1022 | TEST_F(Struct, uint32_t_L_big_MultiPackUnpackingWithOffsetValid) 1023 | { 1024 | uint32_t i = 0x12345678; 1025 | uint32_t o1, o2; 1026 | struct_pack_into(1, buf, ">2L", i, i); 1027 | struct_unpack_from(1, buf, ">2L", &o1, &o2); 1028 | EXPECT_EQ(i, o1); 1029 | EXPECT_EQ(i, o2); 1030 | } 1031 | 1032 | TEST_F(Struct, int64_t_big_PackUnpackingValid) 1033 | { 1034 | int64_t i = 0x1234567887654321LL; 1035 | int64_t o; 1036 | struct_pack(buf, ">q", i); 1037 | struct_unpack(buf, ">q", &o); 1038 | EXPECT_EQ(i, o); 1039 | } 1040 | 1041 | TEST_F(Struct, int64_t_big_MultiPackUnpackingValid) 1042 | { 1043 | int64_t i = 0x1234567887654321LL; 1044 | int64_t o1, o2; 1045 | struct_pack(buf, ">2q", i, i); 1046 | struct_unpack(buf, ">2q", &o1, &o2); 1047 | EXPECT_EQ(i, o1); 1048 | EXPECT_EQ(i, o2); 1049 | } 1050 | 1051 | TEST_F(Struct, int64_t_big_PackUnpackingWithOffsetValid) 1052 | { 1053 | int64_t i = 0x1234567887654321LL; 1054 | int64_t o; 1055 | struct_pack_into(1, buf, ">q", i); 1056 | struct_unpack_from(1, buf, ">q", &o); 1057 | EXPECT_EQ(i, o); 1058 | } 1059 | 1060 | TEST_F(Struct, int64_t_big_MultiPackUnpackingWithOffsetValid) 1061 | { 1062 | int64_t i = 0x1234567887654321LL; 1063 | int64_t o1, o2; 1064 | struct_pack_into(1, buf, ">2q", i, i); 1065 | struct_unpack_from(1, buf, ">2q", &o1, &o2); 1066 | EXPECT_EQ(i, o1); 1067 | EXPECT_EQ(i, o2); 1068 | } 1069 | 1070 | TEST_F(Struct, uint64_t_big_PackUnpackingValid) 1071 | { 1072 | uint64_t i = 0x1234567887654321LL; 1073 | uint64_t o; 1074 | struct_pack(buf, ">Q", i); 1075 | struct_unpack(buf, ">Q", &o); 1076 | EXPECT_EQ(i, o); 1077 | } 1078 | 1079 | TEST_F(Struct, uint64_t_big_MultiPackUnpackingValid) 1080 | { 1081 | uint64_t i = 0x1234567887654321LL; 1082 | uint64_t o1, o2; 1083 | struct_pack(buf, ">2Q", i, i); 1084 | struct_unpack(buf, ">2Q", &o1, &o2); 1085 | EXPECT_EQ(i, o1); 1086 | EXPECT_EQ(i, o2); 1087 | } 1088 | 1089 | TEST_F(Struct, uint64_t_big_PackUnpackingWithOffsetValid) 1090 | { 1091 | uint64_t i = 0x1234567887654321LL; 1092 | uint64_t o; 1093 | struct_pack_into(1, buf, ">Q", i); 1094 | struct_unpack_from(1, buf, ">Q", &o); 1095 | EXPECT_EQ(i, o); 1096 | } 1097 | 1098 | TEST_F(Struct, uint64_t_big_MultiPackUnpackingWithOffsetValid) 1099 | { 1100 | uint64_t i = 0x1234567887654321LL; 1101 | uint64_t o1, o2; 1102 | struct_pack_into(1, buf, ">2Q", i, i); 1103 | struct_unpack_from(1, buf, ">2Q", &o1, &o2); 1104 | EXPECT_EQ(i, o1); 1105 | EXPECT_EQ(i, o2); 1106 | } 1107 | 1108 | TEST_F(Struct, float_big_PackUnpackingValid) 1109 | { 1110 | float i = 3.141592; 1111 | float o; 1112 | struct_pack(buf, ">f", i); 1113 | struct_unpack(buf, ">f", &o); 1114 | EXPECT_DOUBLE_EQ(i, o); 1115 | } 1116 | 1117 | TEST_F(Struct, float_big_MultiPackUnpackingValid) 1118 | { 1119 | float i = 3.141592; 1120 | float o1, o2; 1121 | struct_pack(buf, ">2f", i, i); 1122 | struct_unpack(buf, ">2f", &o1, &o2); 1123 | EXPECT_DOUBLE_EQ(i, o1); 1124 | EXPECT_DOUBLE_EQ(i, o2); 1125 | } 1126 | 1127 | TEST_F(Struct, float_big_PackUnpackingWithOffsetValid) 1128 | { 1129 | float i = 3.141592; 1130 | float o; 1131 | struct_pack_into(1, buf, ">f", i); 1132 | struct_unpack_from(1, buf, ">f", &o); 1133 | EXPECT_DOUBLE_EQ(i, o); 1134 | } 1135 | 1136 | TEST_F(Struct, float_big_MultiPackUnpackingWithOffsetValid) 1137 | { 1138 | float i = 3.141592; 1139 | float o1, o2; 1140 | struct_pack_into(1, buf, ">2f", i, i); 1141 | struct_unpack_from(1, buf, ">2f", &o1, &o2); 1142 | EXPECT_DOUBLE_EQ(i, o1); 1143 | EXPECT_DOUBLE_EQ(i, o2); 1144 | } 1145 | 1146 | TEST_F(Struct, double_big_PackUnpackingValid) 1147 | { 1148 | double i = 3.141592; 1149 | double o; 1150 | struct_pack(buf, ">d", i); 1151 | struct_unpack(buf, ">d", &o); 1152 | EXPECT_DOUBLE_EQ(i, o); 1153 | } 1154 | 1155 | TEST_F(Struct, double_big_MultiPackUnpackingValid) 1156 | { 1157 | double i = 3.141592; 1158 | double o1, o2; 1159 | struct_pack(buf, ">2d", i, i); 1160 | struct_unpack(buf, ">2d", &o1, &o2); 1161 | EXPECT_DOUBLE_EQ(i, o1); 1162 | EXPECT_DOUBLE_EQ(i, o2); 1163 | } 1164 | 1165 | TEST_F(Struct, double_big_PackUnpackingWithOffsetValid) 1166 | { 1167 | double i = 3.141592; 1168 | double o; 1169 | struct_pack_into(1, buf, ">d", i); 1170 | struct_unpack_from(1, buf, ">d", &o); 1171 | EXPECT_DOUBLE_EQ(i, o); 1172 | } 1173 | 1174 | TEST_F(Struct, double_big_MultiPackUnpackingWithOffsetValid) 1175 | { 1176 | double i = 3.141592; 1177 | double o1, o2; 1178 | struct_pack_into(1, buf, ">2d", i, i); 1179 | struct_unpack_from(1, buf, ">2d", &o1, &o2); 1180 | EXPECT_DOUBLE_EQ(i, o1); 1181 | EXPECT_DOUBLE_EQ(i, o2); 1182 | } 1183 | 1184 | TEST_F(Struct, ExamplePacketPackUnpackingValid) 1185 | { 1186 | char msg_id = 1; 1187 | short count = 60000; 1188 | char val = 128; 1189 | int32_t data = 0x11223344; 1190 | char omsg_id; 1191 | short ocount; 1192 | char oval; 1193 | int32_t odata; 1194 | 1195 | struct_pack(buf, "bhbl", 1196 | msg_id, 1197 | count, 1198 | val, 1199 | data); 1200 | struct_unpack(buf, "bhbl", 1201 | &omsg_id, 1202 | &ocount, 1203 | &oval, 1204 | &odata); 1205 | 1206 | EXPECT_TRUE(msg_id == omsg_id); 1207 | EXPECT_TRUE(count == ocount); 1208 | EXPECT_TRUE(val == oval); 1209 | EXPECT_TRUE(data == odata); 1210 | } 1211 | 1212 | TEST_F(Struct, ExamplePacketPackUnpackingWithOffsetValid) 1213 | { 1214 | char msg_id = 1; 1215 | short count = 60000; 1216 | char val = 128; 1217 | int32_t data = 0x11223344; 1218 | char omsg_id; 1219 | short ocount; 1220 | char oval; 1221 | int32_t odata; 1222 | int offset; 1223 | 1224 | struct_pack(buf, "b", msg_id); 1225 | offset = sizeof(msg_id); 1226 | 1227 | struct_pack_into(offset, buf, "h", count); 1228 | offset += sizeof(count); 1229 | 1230 | struct_pack_into(offset, buf, "b", val); 1231 | offset += sizeof(val); 1232 | 1233 | struct_pack_into(offset, buf, "l", data); 1234 | 1235 | // --> 1236 | 1237 | struct_unpack(buf, "b", &omsg_id); 1238 | offset = sizeof(omsg_id); 1239 | 1240 | struct_unpack_from(offset, buf, "h", &ocount); 1241 | offset += sizeof(ocount); 1242 | 1243 | struct_unpack_from(offset, buf, "b", &oval); 1244 | offset += sizeof(oval); 1245 | 1246 | struct_unpack_from(offset, buf, "l", &odata); 1247 | 1248 | EXPECT_TRUE(msg_id == omsg_id); 1249 | EXPECT_TRUE(count == ocount); 1250 | EXPECT_TRUE(val == oval); 1251 | EXPECT_TRUE(data == odata); 1252 | } 1253 | 1254 | TEST_F(Struct, HandleFloatInf) 1255 | { 1256 | float i = 1.0 / 0.0; 1257 | float o; 1258 | struct_pack(buf, "f", i); 1259 | struct_unpack(buf, "f", &o); 1260 | EXPECT_DOUBLE_EQ(i, o); 1261 | } 1262 | 1263 | TEST_F(Struct, HandleFloatNegativeInf) 1264 | { 1265 | float i = -1.0 / 0.0; 1266 | float o; 1267 | struct_pack(buf, "f", i); 1268 | struct_unpack(buf, "f", &o); 1269 | EXPECT_DOUBLE_EQ(i, o); 1270 | } 1271 | 1272 | TEST_F(Struct, HandleFloatInfBigEndian) 1273 | { 1274 | float i = 1.0 / 0.0; 1275 | float o; 1276 | struct_pack(buf, "!f", i); 1277 | struct_unpack(buf, "!f", &o); 1278 | EXPECT_DOUBLE_EQ(i, o); 1279 | } 1280 | 1281 | TEST_F(Struct, HandleFloatNegativeInfBigEndian) 1282 | { 1283 | float i = -1.0 / 0.0; 1284 | float o; 1285 | struct_pack(buf, "!f", i); 1286 | struct_unpack(buf, "!f", &o); 1287 | EXPECT_DOUBLE_EQ(i, o); 1288 | } 1289 | 1290 | TEST_F(Struct, HandleDoubleInf) 1291 | { 1292 | double i = 1.0 / 0.0; 1293 | double o; 1294 | struct_pack(buf, "d", i); 1295 | struct_unpack(buf, "d", &o); 1296 | EXPECT_DOUBLE_EQ(i, o); 1297 | } 1298 | 1299 | TEST_F(Struct, HandleDoubleNegativeInf) 1300 | { 1301 | double i = -1.0 / 0.0; 1302 | double o; 1303 | struct_pack(buf, "d", i); 1304 | struct_unpack(buf, "d", &o); 1305 | EXPECT_DOUBLE_EQ(i, o); 1306 | } 1307 | 1308 | TEST_F(Struct, HandleDoubleInfBigEndian) 1309 | { 1310 | double i = 1.0 / 0.0; 1311 | double o; 1312 | struct_pack(buf, "!d", i); 1313 | struct_unpack(buf, "!d", &o); 1314 | EXPECT_DOUBLE_EQ(i, o); 1315 | } 1316 | 1317 | TEST_F(Struct, HandleDoubleNegativeInfBigEndian) 1318 | { 1319 | double i = -1.0 / 0.0; 1320 | double o; 1321 | struct_pack(buf, "!d", i); 1322 | struct_unpack(buf, "!d", &o); 1323 | EXPECT_DOUBLE_EQ(i, o); 1324 | } 1325 | 1326 | TEST_F(Struct, HandleFloatNan) 1327 | { 1328 | float i = 0.0 / 0.0; 1329 | float o; 1330 | struct_pack(buf, "f", i); 1331 | struct_unpack(buf, "f", &o); 1332 | EXPECT_TRUE(i != o); // NaN != NaN => true 1333 | } 1334 | 1335 | TEST_F(Struct, HandleFloatNanBigEndian) 1336 | { 1337 | float i = 0.0 / 0.0; 1338 | float o; 1339 | struct_pack(buf, "!f", i); 1340 | struct_unpack(buf, "!f", &o); 1341 | EXPECT_TRUE(i != o); // NaN != NaN => true 1342 | } 1343 | 1344 | TEST_F(Struct, HandleDoubleNan) 1345 | { 1346 | double i = 0.0 / 0.0; 1347 | double o; 1348 | struct_pack(buf, "d", i); 1349 | struct_unpack(buf, "d", &o); 1350 | EXPECT_TRUE(i != o); // NaN != NaN => true 1351 | } 1352 | 1353 | TEST_F(Struct, HandleDoubleNanBigEndian) 1354 | { 1355 | double i = 0.0 / 0.0; 1356 | double o; 1357 | struct_pack(buf, "!d", i); 1358 | struct_unpack(buf, "!d", &o); 1359 | EXPECT_TRUE(i != o); // NaN != NaN => true 1360 | } 1361 | 1362 | TEST_F(Struct, PackUnpackingStringUsingSameBuffer) 1363 | { 1364 | char str[32]; 1365 | char fmt[32]; 1366 | 1367 | memset(str, 0, sizeof(str)); 1368 | memset(fmt, 0, sizeof(fmt)); 1369 | 1370 | strcpy(str, "test"); 1371 | snprintf(fmt, sizeof(fmt), "%ds", (int)strlen(str)); 1372 | // checking the result of snprintf() omitted.. 1373 | 1374 | struct_pack(str, fmt, str); 1375 | struct_unpack(str, fmt, str); 1376 | EXPECT_STREQ(str, "test"); 1377 | } 1378 | 1379 | TEST_F(Struct, varint_PackUnpackingValid) 1380 | { 1381 | uint64_t i = 0x1234567887654321LL; 1382 | uint64_t o = 0; 1383 | struct_pack(buf, ">V", i); 1384 | struct_unpack(buf, ">V", &o); 1385 | EXPECT_EQ(i, o); 1386 | } 1387 | 1388 | TEST_F(Struct, varint_SignedPackUnpackingValid) 1389 | { 1390 | int64_t i = -18014398573270210LL; 1391 | int64_t o; 1392 | struct_pack(buf, ">v", i); 1393 | struct_unpack(buf, ">v", &o); 1394 | EXPECT_EQ(i, o); 1395 | } 1396 | 1397 | TEST_F(Struct, varint_MultiPackUnpackingValid) 1398 | { 1399 | uint64_t i1 = 7182, i2 = 0x1234567887654321LL; 1400 | uint64_t o1, o2; 1401 | struct_pack(buf, ">2V", i1, i2); 1402 | struct_unpack(buf, ">2V", &o1, &o2); 1403 | EXPECT_EQ(i1, o1); 1404 | EXPECT_EQ(i2, o2); 1405 | } 1406 | 1407 | } // namespace 1408 | 1409 | int main(int argc, char *argv[]) 1410 | { 1411 | ::testing::InitGoogleTest(&argc, argv); 1412 | return RUN_ALL_TESTS(); 1413 | } 1414 | --------------------------------------------------------------------------------