From 68208dddc1df4dfc82e483aff49f5f1fa6e04c77 Mon Sep 17 00:00:00 2001 From: undefined Date: Sat, 16 Dec 2023 19:59:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=9E=E6=BB=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 有个dll就有个吧( --- .github/workflows/build-ci.yaml | 9 +- .github/workflows/build-release.yaml | 134 +++--- .gitignore | 22 +- CMakeLists.txt | 114 +++-- LICENSE.md | 50 +- README.md | 44 +- cli/main.c | 304 ++++++------ core/Json.h | 14 +- core/parser/parser.c | 610 +++++++++++------------ core/parser/parser.h | 22 +- core/types/JsonArray.c | 108 ++--- core/types/JsonArray.h | 28 +- core/types/JsonObject.c | 56 +-- core/types/JsonObject.h | 26 +- core/types/JsonString.c | 260 +++++----- core/types/JsonString.h | 36 +- core/types/JsonValue.c | 48 +- core/types/JsonValue.h | 68 +-- core/utils/outputer.c | 268 +++++------ core/utils/outputer.h | 46 +- cutest/CuTest.c | 690 +++++++++++++-------------- cutest/CuTest.h | 234 ++++----- test/stringTest.c | 8 +- 23 files changed, 1599 insertions(+), 1600 deletions(-) diff --git a/.github/workflows/build-ci.yaml b/.github/workflows/build-ci.yaml index 2f2d471..916a30b 100644 --- a/.github/workflows/build-ci.yaml +++ b/.github/workflows/build-ci.yaml @@ -24,17 +24,18 @@ jobs: - name: set up Msys2 uses: msys2/setup-msys2@v2 with: - msystem: mingw64 + msystem: ucrt64 install: >- - mingw-w64-x86_64-toolchain - mingw-w64-x86_64-cmake libiconv-devel + cmake + gcc + ninja pkg-config + - name: build shell: msys2 {0} run: | mkdir build && cd build - export CC=gcc cmake -G Ninja -DCMAKE_BUILD_TYPE=DEBUG .. && cmake --build . - uses: actions/upload-artifact@v3 diff --git a/.github/workflows/build-release.yaml b/.github/workflows/build-release.yaml index ba6d716..29e4e4b 100644 --- a/.github/workflows/build-release.yaml +++ b/.github/workflows/build-release.yaml @@ -1,68 +1,68 @@ -on: - workflow_dispatch: - push: - branches: - - master - - -jobs: - check-release: - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - - name: Check Release Commit - run: | - if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/master" ]]; then - releaseField=$(git log -1 --pretty=format:'%B' | grep -oE 'RELEASE: [^\n]+' | cut -d' ' -f2) - - if [[ -n "$releaseField" ]]; then - echo "Release field found. Continuing with subsequent jobs." - else - echo "No release field found. Exiting with code 78." - exit 78 # Exit code 78 skips subsequent jobs - fi - else - echo "Not a push to master branch. Exiting with code 78." - exit 78 # Exit code 78 skips subsequent jobs - fi - shell: bash - build-linux: - needs: check-release - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - name: build - run: | - mkdir build && cd build && cmake -G Ninja -DCMAKE_BUILD_TYPE=RELEASE .. && cmake --build . - - uses: actions/upload-artifact@v3 - with: - name: linux - path: build/json - build-windows: - needs: check-release - runs-on: windows-latest - steps: - - uses: actions/checkout@master - - name: set up Msys2 - uses: msys2/setup-msys2@v2 - with: - msystem: ucrt64 - install: >- - libiconv-devel - cmake - gcc - ninja - pkg-config - - - name: build - shell: msys2 {0} - run: | - mkdir build && cd build - cmake -G Ninja -DCMAKE_BUILD_TYPE=RELEASE .. && cmake --build . - - uses: actions/upload-artifact@v3 - with: - name: windows +on: + workflow_dispatch: + push: + branches: + - master + + +jobs: + check-release: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Check Release Commit + run: | + if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == "refs/heads/master" ]]; then + releaseField=$(git log -1 --pretty=format:'%B' | grep -oE 'RELEASE: [^\n]+' | cut -d' ' -f2) + + if [[ -n "$releaseField" ]]; then + echo "Release field found. Continuing with subsequent jobs." + else + echo "No release field found. Exiting with code 78." + exit 78 # Exit code 78 skips subsequent jobs + fi + else + echo "Not a push to master branch. Exiting with code 78." + exit 78 # Exit code 78 skips subsequent jobs + fi + shell: bash + build-linux: + needs: check-release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: build + run: | + mkdir build && cd build && cmake -G Ninja -DCMAKE_BUILD_TYPE=RELEASE .. && cmake --build . + - uses: actions/upload-artifact@v3 + with: + name: linux + path: build/json + build-windows: + needs: check-release + runs-on: windows-latest + steps: + - uses: actions/checkout@master + - name: set up Msys2 + uses: msys2/setup-msys2@v2 + with: + msystem: ucrt64 + install: >- + libiconv-devel + cmake + gcc + ninja + pkg-config + + - name: build + shell: msys2 {0} + run: | + mkdir build && cd build + cmake -G Ninja -DCMAKE_BUILD_TYPE=RELEASE .. && cmake --build . + - uses: actions/upload-artifact@v3 + with: + name: windows path: build/json.exe \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1cd49c7..8c7791d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,12 @@ -.vs/ -.idea/ -x64/ -cmake-build-debug/ -cmake-build-release/ -cmake-build-debug-mingw/ -*.pdb - -lcui-quick-start.zip -package-lock.json --g/ +.vs/ +.idea/ +x64/ +cmake-build-debug/ +cmake-build-release/ +cmake-build-debug-mingw/ +*.pdb + +lcui-quick-start.zip +package-lock.json +-g/ build/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 185e84c..32acda6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,59 +1,57 @@ -cmake_minimum_required(VERSION 3.27) - -PROJECT(JsonParser C) -set(CMAKE_C_STANDARD 17) - -find_package(Iconv REQUIRED) -add_definitions(-DLOCALEDIR="\"${CMAKE_INSTALL_PREFIX}/share/locale\"") - - -add_library(jsonParserLib - core/Json.h - core/parser/parser.h - core/types/JsonValue.h - core/types/JsonArray.h - core/types/JsonObject.h - core/types/JsonString.h - core/utils/outputer.h - core/utils/outputer.c - core/parser/parser.c - core/types/JsonValue.c - core/types/JsonArray.c - core/types/JsonObject.c - core/types/JsonString.c -) -target_link_libraries(jsonParserLib PRIVATE Iconv::Iconv) - -add_executable(json - cli/main.c -) -target_include_directories(json PRIVATE - core -) -target_link_libraries(json PRIVATE - jsonParserLib -) - -add_library(cutest - cutest/CuTest.h - cutest/CuTest.c -) - -add_executable(string_test - test/stringTest.c -) - -target_include_directories(string_test PRIVATE - core - cutest -) -target_link_libraries(string_test PRIVATE - cutest - jsonParserLib -) - -enable_testing() -add_test( - NAME "String Test" - COMMAND string_test +cmake_minimum_required(VERSION 3.27) + +PROJECT(JsonParser C) +set(CMAKE_C_STANDARD 17) + +find_package(Iconv REQUIRED) + +add_library(jsonParserLib + core/Json.h + core/parser/parser.h + core/types/JsonValue.h + core/types/JsonArray.h + core/types/JsonObject.h + core/types/JsonString.h + core/utils/outputer.h + core/utils/outputer.c + core/parser/parser.c + core/types/JsonValue.c + core/types/JsonArray.c + core/types/JsonObject.c + core/types/JsonString.c +) +target_link_libraries(jsonParserLib PRIVATE Iconv::Iconv) + +add_executable(json + cli/main.c +) +target_include_directories(json PRIVATE + core +) +target_link_libraries(json PRIVATE + jsonParserLib +) + +add_library(cutest + cutest/CuTest.h + cutest/CuTest.c +) + +add_executable(string_test + test/stringTest.c +) + +target_include_directories(string_test PRIVATE + core + cutest +) +target_link_libraries(string_test PRIVATE + cutest + jsonParserLib +) + +enable_testing() +add_test( + NAME "String Test" + COMMAND string_test ) \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md index c97d747..c64b5ca 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,25 +1,25 @@ -The MIT License (MIT) -===================== -Copyright © `2023` `undefined-ux` - - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the “Software”), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +The MIT License (MIT) +===================== +Copyright © `2023` `undefined-ux` + + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the “Software”), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index db49cc3..5d3685f 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,22 @@ -# 大一 C语言大作业 - -## json解析器 - -[下载](https://github.com/undefined-ux/json-parser-homework/releases) [CI构建](https://github.com/undefined-ux/json-parser-homework/actions) - -[文档](https://undefined-ux.github.io/json-parser-homework) -### 命令行版本 -#### 使用 -``` -如果未指定输入或输出文件,则程序将默认使用标准输入或标准输出。 -注意:-c / --compress 和 -f / --format 选项不能同时使用 --if, --input 指定输入文件(默认为标准输入) --of, --output 指定输出文件(默认为标准输出) --f, --format 使用树形缩进输出格式化的JSON --h, --help 显示此帮助并退出 --c, --compress 输出压缩的JSON --u, --utf 启用utf-8编码支持 -``` - -### GUI -GUI目前仍然是饼, 没做 +# 大一 C语言大作业 + +## json解析器 + +[下载](https://github.com/undefined-ux/json-parser-homework/releases) [CI构建](https://github.com/undefined-ux/json-parser-homework/actions) + +[文档](https://undefined-ux.github.io/json-parser-homework) +### 命令行版本 +#### 使用 +``` +如果未指定输入或输出文件,则程序将默认使用标准输入或标准输出。 +注意:-c / --compress 和 -f / --format 选项不能同时使用 +-if, --input 指定输入文件(默认为标准输入) +-of, --output 指定输出文件(默认为标准输出) +-f, --format 使用树形缩进输出格式化的JSON +-h, --help 显示此帮助并退出 +-c, --compress 输出压缩的JSON +-u, --utf 启用utf-8编码支持 +``` + +### GUI +GUI目前仍然是饼, 没做 diff --git a/cli/main.c b/cli/main.c index 09f1d25..b0f064c 100644 --- a/cli/main.c +++ b/cli/main.c @@ -1,152 +1,152 @@ -#include -#include -#include -#include -#include -#include "Json.h" - - -// 结构体用于存储命令行参数的值 -struct CommandLineArgs { - FILE* input; // 输入流 - FILE* output; // 输出流 - int compress; // 是否压缩 - int format; // 是否格式化 - // int utf8Text; // 是否为utf-8 文本 是则需资源回收时删除中间文件 - // char* convertCacheFilePath; // 为utf-8文本时转换为gbk格式时生成的临时文件 - // char* outputFilePath; // 需要输出文件路径, 当为utf-8文本时用于转换回utf-8文本 -}; - -// 函数声明 -struct CommandLineArgs parseCommandLineArgs(int argc, char* argv[]); - -int main(const int argc, char* argv[]) { - // setlocale(LC_ALL, ""); // 设置本地化环境以支持宽字符 - const struct CommandLineArgs args = parseCommandLineArgs(argc, argv); - // 设置输入输出流 - // 默认为标准输入输出 - setInputStream(args.input); - setOutputStream(args.output); - - //解析Json - const struct JsonVal* json = parseValue(); - if (args.compress) { printJsonVal(json, args.output == stdout); } - else if (args.format) { printfJsonVal(json, 0, args.output == stdout); } - - //destoryJsonVal(json); - if (args.input != stdin) { fclose(args.input); } - if (args.output != stdout) { - fclose(args.output); - } - return 0; -} - -// 函数定义:解析命令行参数 -struct CommandLineArgs parseCommandLineArgs(int argc, char* argv[]) { - struct CommandLineArgs args; - - // 初始化结构体成员 - args.input = stdin; - args.output = stdout; - args.compress = 0; - args.format = 1; - // args.utf8Text = 0; - // args.convertCacheFilePath = "__cache.json"; - // 标记是否已经出现了--format或--compress - int formatSeen = 0; - int compressSeen = 0; - // 解析命令行参数 - for (int i = 1; i < argc; ++i) { - if (strcmp(argv[i], "--output") == 0 || strcmp(argv[i], "-of") == 0) { - // 指定输出流 - if (i + 1 < argc) { - fputs("Output: ", stdout);fputs(argv[i + 1], stdout); fputs("\n", stdout); - args.output = fopen(argv[i + 1], "w"); - // args.outputFilePath = argv[i + 1]; - if (args.output == NULL) { - perror("Error opening output file"); - exit(EXIT_FAILURE); - } - i++; // 跳过下一个参数,因为它是文件路径 - } - else { - fputs("Error: --output option requires a file path.\n", stderr); - exit(EXIT_FAILURE); - } - } - else if (strcmp(argv[i], "--input") == 0 || strcmp(argv[i], "-if") == 0) { - // 指定输入流 - if (i + 1 < argc) { - args.input = fopen(argv[i + 1], "r"); - // FILE* f = fopen(argv[i + 1], "r"); - - // if (isUtf8(f)) { - // printf("INFO: Is UTF-8 Text\n"); - // args.input = convertUtf8ToGbk(f); - // args.utf8Text = 1; - // } - // else { args.input = fopen(argv[i + 1], "r"); } - if (args.input == NULL) { - perror("Error opening input file"); - exit(EXIT_FAILURE); - } - i++; // 跳过下一个参数,因为它是文件路径 - } - else { - fputs("Error: --input option requires a file path.\n", stderr); - exit(EXIT_FAILURE); - } - } - else if (strcmp(argv[i], "--compress") == 0 || strcmp(argv[i], "-c") == 0) { - // 压缩格式输出Json - if (formatSeen) { - fputs("Error: --compress and --format cannot be used together.\n", stderr); - exit(EXIT_FAILURE); - } - args.compress = 1; - args.format = 0; - compressSeen = 1; - } - else if (strcmp(argv[i], "--format") == 0 || strcmp(argv[i], "-f") == 0) { - // 格式化输出Json - if (compressSeen) { - fputs("Error: --compress and --format cannot be used together.\n", stderr); - exit(EXIT_FAILURE); - } - args.format = 1; - formatSeen = 1; - } - else if (strcmp(argv[i], "--utf") == 0 || strcmp(argv[i], "-u") == 0) { - // 本地字符集设置为 UTF-8 - setlocale(LC_ALL, ""); - } - else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { - setlocale(LC_ALL, ""); - puts("用法:json [选项]...\n"); - puts("从输入中解析和格式化JSON数据,可选择压缩或格式化输出。\n\n"); - - puts("长选项的强制性参数对于短选项也是强制性的。\n"); - puts(" -if, --input 指定输入文件(默认为标准输入)\n"); - puts(" -of, --output 指定输出文件(默认为标准输出)\n"); - puts(" -f, --format 使用树形缩进输出格式化的JSON\n"); - puts(" -c, --compress 输出压缩的JSON\n"); - puts(" -u, --utf 启用utf-8编码支持\n"); - puts(" -h, --help 显示此帮助并退出\n\n"); - - puts("示例:\n"); - puts(" json -if input.json -of output.json -f\n"); - puts(" json --input=input.json --output=output.json --compress\n\n"); - - puts("如果未指定输入或输出文件,则程序将默认使用标准输入或标准输出。\n\n"); - - puts("注意:--compress 和 --format 选项不能同时使用。\n"); - exit(0); - } - else { - fprintf(stderr, "Unknown option: %s\n", argv[i]); - exit(EXIT_FAILURE); - } - } - - return args; -} +#include +#include +#include +#include +#include +#include "Json.h" + + +// 结构体用于存储命令行参数的值 +struct CommandLineArgs { + FILE* input; // 输入流 + FILE* output; // 输出流 + int compress; // 是否压缩 + int format; // 是否格式化 + // int utf8Text; // 是否为utf-8 文本 是则需资源回收时删除中间文件 + // char* convertCacheFilePath; // 为utf-8文本时转换为gbk格式时生成的临时文件 + // char* outputFilePath; // 需要输出文件路径, 当为utf-8文本时用于转换回utf-8文本 +}; + +// 函数声明 +struct CommandLineArgs parseCommandLineArgs(int argc, char* argv[]); + +int main(const int argc, char* argv[]) { + // setlocale(LC_ALL, ""); // 设置本地化环境以支持宽字符 + const struct CommandLineArgs args = parseCommandLineArgs(argc, argv); + // 设置输入输出流 + // 默认为标准输入输出 + setInputStream(args.input); + setOutputStream(args.output); + + //解析Json + const struct JsonVal* json = parseValue(); + if (args.compress) { printJsonVal(json, args.output == stdout); } + else if (args.format) { printfJsonVal(json, 0, args.output == stdout); } + + //destoryJsonVal(json); + if (args.input != stdin) { fclose(args.input); } + if (args.output != stdout) { + fclose(args.output); + } + return 0; +} + +// 函数定义:解析命令行参数 +struct CommandLineArgs parseCommandLineArgs(int argc, char* argv[]) { + struct CommandLineArgs args; + + // 初始化结构体成员 + args.input = stdin; + args.output = stdout; + args.compress = 0; + args.format = 1; + // args.utf8Text = 0; + // args.convertCacheFilePath = "__cache.json"; + // 标记是否已经出现了--format或--compress + int formatSeen = 0; + int compressSeen = 0; + // 解析命令行参数 + for (int i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--output") == 0 || strcmp(argv[i], "-of") == 0) { + // 指定输出流 + if (i + 1 < argc) { + fputs("Output: ", stdout);fputs(argv[i + 1], stdout); fputs("\n", stdout); + args.output = fopen(argv[i + 1], "w"); + // args.outputFilePath = argv[i + 1]; + if (args.output == NULL) { + perror("Error opening output file"); + exit(EXIT_FAILURE); + } + i++; // 跳过下一个参数,因为它是文件路径 + } + else { + fputs("Error: --output option requires a file path.\n", stderr); + exit(EXIT_FAILURE); + } + } + else if (strcmp(argv[i], "--input") == 0 || strcmp(argv[i], "-if") == 0) { + // 指定输入流 + if (i + 1 < argc) { + args.input = fopen(argv[i + 1], "r"); + // FILE* f = fopen(argv[i + 1], "r"); + + // if (isUtf8(f)) { + // printf("INFO: Is UTF-8 Text\n"); + // args.input = convertUtf8ToGbk(f); + // args.utf8Text = 1; + // } + // else { args.input = fopen(argv[i + 1], "r"); } + if (args.input == NULL) { + perror("Error opening input file"); + exit(EXIT_FAILURE); + } + i++; // 跳过下一个参数,因为它是文件路径 + } + else { + fputs("Error: --input option requires a file path.\n", stderr); + exit(EXIT_FAILURE); + } + } + else if (strcmp(argv[i], "--compress") == 0 || strcmp(argv[i], "-c") == 0) { + // 压缩格式输出Json + if (formatSeen) { + fputs("Error: --compress and --format cannot be used together.\n", stderr); + exit(EXIT_FAILURE); + } + args.compress = 1; + args.format = 0; + compressSeen = 1; + } + else if (strcmp(argv[i], "--format") == 0 || strcmp(argv[i], "-f") == 0) { + // 格式化输出Json + if (compressSeen) { + fputs("Error: --compress and --format cannot be used together.\n", stderr); + exit(EXIT_FAILURE); + } + args.format = 1; + formatSeen = 1; + } + else if (strcmp(argv[i], "--utf") == 0 || strcmp(argv[i], "-u") == 0) { + // 本地字符集设置为 UTF-8 + setlocale(LC_ALL, "zh_CN.UTF-8"); + } + else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + setlocale(LC_ALL, "zh_CN.UTF-8"); + puts("用法:json [选项]...\n"); + puts("从输入中解析和格式化JSON数据,可选择压缩或格式化输出。\n\n"); + + puts("长选项的强制性参数对于短选项也是强制性的。\n"); + puts(" -if, --input 指定输入文件(默认为标准输入)\n"); + puts(" -of, --output 指定输出文件(默认为标准输出)\n"); + puts(" -f, --format 使用树形缩进输出格式化的JSON\n"); + puts(" -c, --compress 输出压缩的JSON\n"); + puts(" -u, --utf 启用utf-8编码支持\n"); + puts(" -h, --help 显示此帮助并退出\n\n"); + + puts("示例:\n"); + puts(" json -if input.json -of output.json -f\n"); + puts(" json --input=input.json --output=output.json --compress\n\n"); + + puts("如果未指定输入或输出文件,则程序将默认使用标准输入或标准输出。\n\n"); + + puts("注意:--compress 和 --format 选项不能同时使用。\n"); + exit(0); + } + else { + fprintf(stderr, "Unknown option: %s\n", argv[i]); + exit(EXIT_FAILURE); + } + } + + return args; +} diff --git a/core/Json.h b/core/Json.h index 79e5445..353bf38 100644 --- a/core/Json.h +++ b/core/Json.h @@ -1,7 +1,7 @@ -#pragma once -#include "types/JsonObject.h" -#include "types/JsonString.h" -#include "types/JsonValue.h" -#include "types/JsonArray.h" -#include "utils/outputer.h" -#include "parser/parser.h" +#pragma once +#include "types/JsonObject.h" +#include "types/JsonString.h" +#include "types/JsonValue.h" +#include "types/JsonArray.h" +#include "utils/outputer.h" +#include "parser/parser.h" diff --git a/core/parser/parser.c b/core/parser/parser.c index dbbc569..667d90c 100644 --- a/core/parser/parser.c +++ b/core/parser/parser.c @@ -1,305 +1,305 @@ -#include "parser.h" -#include -#include - -static FILE* f = 0; - -void setInputStream(FILE* stream) { f = stream; } - -void ignoreWhiteCharactor() { - char c; - while ((c = fgetc(f)) != EOF && (c == ' ' || c == '\r' || c == '\n' || c == '\t')); - if (!(c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == EOF)) ungetc(c, f); -} - - -struct JsonVal* parseValue() { - ignoreWhiteCharactor(); - const char c = fgetc(f); - if (c == '{') return parseObject(); - if (c == '[') return parseArray(); - if (c == 'n' || c == 'N') { - ungetc(c, f); - return parseNull(); - } - if (c == 't' || c == 'T' || c == 'F' || c == 'f') { - ungetc(c, f); - return parseBool(); - } - if (c <= '9' && c >= '0' || c == '-') { - ungetc(c, f); - return parseNumber(); - } - if (c == '"' || c == '\'') return parseString(c); - fprintf( - stderr, - "Unexcepted token %c at %llu", - c, ftell(f) / sizeof(char) - ); - exit(1); -} - -struct JsonString* parseStringToStr(char token) { - char c; - struct JsonString* str = JsonString_New(); - const size_t pos = ftell(f) / sizeof(char); - - while ((c = fgetc(f)) && c != EOF && c != token) { - if (c == '\\') { - JsonStringPushBackChar(c, str); - c = fgetc(f); - if (c == EOF) { - fprintf(stderr, "Unexpected EOF after escape character.\tString value parse begin with %llu\n", pos); - exit(1); - } - JsonStringPushBackChar(c, str); - } - else JsonStringPushBackChar(c, str); - } - - if (c != token) { - fprintf(stderr, "Expected character %c, but got EOF.\tString value parse begin with %llu\n", token, pos); - exit(1); - } - return str; -} - -struct JsonVal* parseString(char token) { - struct JsonString* str = parseStringToStr(token); - - struct JsonVal* res = malloc(sizeof(struct JsonVal)); - if (res == NULL) { - // Memory allocation failure (OOM) - // Handle the error and exit - exit(1); - } - - res->type = STRING; - res->val = str; - return res; -} - - -struct JsonVal* parseNumber() { - char c; - struct JsonString* str = JsonString_New(); - int isFloat = 0, isNegative = 0; - - // 修复了循环条件,添加了对换行符和空格的判断 - while ((c = fgetc(f)) != EOF && ((c >= '0' && c <= '9') || c == '-' || c == '.')) { - JsonStringPushBackChar(c, str); - if (c == '-' && !isNegative) { isNegative = 1; } - else if (c == '-' && isNegative) { - fprintf( - stderr, - "Expected character [1-9], but got '.' at %llu", - ftell(f) / sizeof(char) - ); - exit(1); - } - if (c == '.' && !isFloat) { isFloat = 1; } - else if (c == '.' && isFloat) { - fprintf( - stderr, - "Expected character [1-9], but got '.' at %llu", - ftell(f) / sizeof(char) - ); - exit(1); - } - } - - struct JsonVal* res = malloc(sizeof(struct JsonVal)); - if (res == NULL) { - // 内存分配失败 - exit(1); - } - ungetc(c, f); - res->type = NUMBER; res->val = str; - return res; -} - -struct JsonVal* parseBool() { - char c; - // true or false - struct JsonVal* res = malloc(sizeof(struct JsonVal)); - if (res == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - - res->type = BOOL; - if ((c = fgetc(f)) == 't' || c == 'T') { - // true - const char trueStr[] = "true"; - for (int i = 1; i < 4; i++) { - c = fgetc(f); - if (c != trueStr[i] && c != trueStr[i] - 'a' + 'A') { - fprintf( - stderr, - "Unexcepted value at %llu", - ftell(f) / sizeof(char) - ); // 写入报错到标准错误流 - exit(1); - } - } - c = fgetc(f); - if (c != ' ' && c != '\n' && c != ',' && c != ']' && c != '}') { - fprintf( - stderr, - "Unexcepted token %c at %llu", - c, ftell(f) / sizeof(char) - ); // 写入报错到标准错误流 - exit(1); - } - ungetc(c, f); - res->val = JsonStringFromCharArray("true"); - } - else if (c == 'f' || c == 'F') { - // false - const char falseStr[] = "false"; - for (int i = 1; i < 5; i++) { - c = fgetc(f); - if (c != falseStr[i] && c != falseStr[i] - 'a' + 'A') { - fprintf( - stderr, - "Unxcepted token %c at %llu", - c, ftell(f) / sizeof(char) - ); // 写入报错到标准错误流 - exit(1); - } - } - c = fgetc(f); - if (c != ' ' && c != '\n' && c != ',' && c != ']' && c != '}') { - fprintf( - stderr, - "Unxcepted token %c at %llu", - c, ftell(f) / sizeof(char) - ); // 写入报错到标准错误流 - exit(1); - } - ungetc(c, f); - - if (res == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - res->val = JsonStringFromCharArray("false"); - return res; - } - else { - fprintf( - stderr, - "Unexcepted token %c at %llu", - c, ftell(f) / sizeof(char) - ); // 写入报错到标准错误流 - exit(1); - } - return res; -} - - -struct JsonVal* parseObject() { - char c; - struct JsonObj* obj = malloc(sizeof(struct JsonObj)); - struct JsonVal* res = malloc(sizeof(struct JsonVal)); - if (res == NULL) exit(1); - if (obj == NULL) exit(1); - res->type = OBJECT; - - const struct JsonString* keyVal = NULL; - obj->size = 0; - - while ((c = fgetc(f)) != EOF && c != '}') { - if (c == ' ' || c == '\n' || c == '\r' || c == ',') continue; - if (c == '"' || c == '\'') keyVal = parseStringToStr(c); - - else if (c == ':') { - const struct JsonVal* Val = parseValue(); - if(keyVal == NULL) { - fprintf(stderr, "Unexcepted token %c at %llu", c, ftell(f) / sizeof(char)); - exit(1); - } - JsonObjInsert(obj, keyVal, Val); ignoreWhiteCharactor(); - c = fgetc(f); - if(c != ',' && c != '}') { - fprintf(stderr, "Unexcepted token %c at %llu", c, ftell(f) / sizeof(char)); - exit(1); - } - if(c == '}') { - ungetc(c, f); - } - } - else { - fprintf(stderr, "Unexcepted token %c at %llu", c, ftell(f) / sizeof(char)); - exit(1); - } - } - if (c != '}') { - fprintf(stderr, "Unexcepted token EOF at %llu", ftell(f) / sizeof(char)); - exit(1); - } - res->obj = obj; - return res; -} - -struct JsonVal* parseArray() { - struct JsonArray* arr = malloc(sizeof(struct JsonArray)); - struct JsonVal* res = malloc(sizeof(struct JsonVal)); - - if (arr == NULL || res == NULL) exit(1); - res->type = ARRAY; - arr->length = 0; - char c; - ignoreWhiteCharactor(f); - - while ((c = fgetc(f)) != EOF && c != ']') { - ignoreWhiteCharactor(); - if (c != ',') ungetc(c, f); - struct JsonVal* val = parseValue(); - JsonArrayPushBack(arr, val); - - ignoreWhiteCharactor(); - } - if (c != ']') { - fprintf(stderr, "Unexcepted token EOF at %llu", ftell(f) / sizeof(char)); - exit(1); - } - res->arr = arr; - return res; -} - -struct JsonVal* parseNull() { - const char nullStr[] = "null"; - char c; - for (int i = 0; i < 4; i++) { - c = fgetc(f); - if (c != nullStr[i] && c != nullStr[i] - 'a' + 'A') { - fprintf( - stderr, - "Unexcepted token %c at %llu", - c, ftell(f) / sizeof(char) - ); // 写入报错到标准错误流 - exit(1); - } - } - c = fgetc(f); - if (c != ' ' && c != '\n' && c != ',' && c != ']' && c != '}') { - fprintf( - stderr, - "Unexcepted token %c at %llu", - c, ftell(f) / sizeof(char) - ); // 写入报错到标准错误流 - exit(1); - } - ungetc(c, f); - struct JsonVal* res = (struct JsonVal*)malloc(sizeof(struct JsonVal)); - if (res == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - res->type = NONE; res->val = NULL; - return res; -} +#include "parser.h" +#include +#include + +static FILE* f = 0; + +void setInputStream(FILE* stream) { f = stream; } + +void ignoreWhiteCharactor() { + char c; + while ((c = fgetc(f)) != EOF && (c == ' ' || c == '\r' || c == '\n' || c == '\t')); + if (!(c == ' ' || c == '\r' || c == '\n' || c == '\t' || c == EOF)) ungetc(c, f); +} + + +struct JsonVal* parseValue() { + ignoreWhiteCharactor(); + const char c = fgetc(f); + if (c == '{') return parseObject(); + if (c == '[') return parseArray(); + if (c == 'n' || c == 'N') { + ungetc(c, f); + return parseNull(); + } + if (c == 't' || c == 'T' || c == 'F' || c == 'f') { + ungetc(c, f); + return parseBool(); + } + if (c <= '9' && c >= '0' || c == '-') { + ungetc(c, f); + return parseNumber(); + } + if (c == '"' || c == '\'') return parseString(c); + fprintf( + stderr, + "Unexcepted token %c at %llu", + c, ftell(f) / sizeof(char) + ); + exit(1); +} + +struct JsonString* parseStringToStr(char token) { + char c; + struct JsonString* str = JsonString_New(); + const size_t pos = ftell(f) / sizeof(char); + + while ((c = fgetc(f)) && c != EOF && c != token) { + if (c == '\\') { + JsonStringPushBackChar(c, str); + c = fgetc(f); + if (c == EOF) { + fprintf(stderr, "Unexpected EOF after escape character.\tString value parse begin with %llu\n", pos); + exit(1); + } + JsonStringPushBackChar(c, str); + } + else JsonStringPushBackChar(c, str); + } + + if (c != token) { + fprintf(stderr, "Expected character %c, but got EOF.\tString value parse begin with %llu\n", token, pos); + exit(1); + } + return str; +} + +struct JsonVal* parseString(char token) { + struct JsonString* str = parseStringToStr(token); + + struct JsonVal* res = malloc(sizeof(struct JsonVal)); + if (res == NULL) { + // Memory allocation failure (OOM) + // Handle the error and exit + exit(1); + } + + res->type = STRING; + res->val = str; + return res; +} + + +struct JsonVal* parseNumber() { + char c; + struct JsonString* str = JsonString_New(); + int isFloat = 0, isNegative = 0; + + // 修复了循环条件,添加了对换行符和空格的判断 + while ((c = fgetc(f)) != EOF && ((c >= '0' && c <= '9') || c == '-' || c == '.')) { + JsonStringPushBackChar(c, str); + if (c == '-' && !isNegative) { isNegative = 1; } + else if (c == '-' && isNegative) { + fprintf( + stderr, + "Expected character [1-9], but got '.' at %llu", + ftell(f) / sizeof(char) + ); + exit(1); + } + if (c == '.' && !isFloat) { isFloat = 1; } + else if (c == '.' && isFloat) { + fprintf( + stderr, + "Expected character [1-9], but got '.' at %llu", + ftell(f) / sizeof(char) + ); + exit(1); + } + } + + struct JsonVal* res = malloc(sizeof(struct JsonVal)); + if (res == NULL) { + // 内存分配失败 + exit(1); + } + ungetc(c, f); + res->type = NUMBER; res->val = str; + return res; +} + +struct JsonVal* parseBool() { + char c; + // true or false + struct JsonVal* res = malloc(sizeof(struct JsonVal)); + if (res == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + + res->type = BOOL; + if ((c = fgetc(f)) == 't' || c == 'T') { + // true + const char trueStr[] = "true"; + for (int i = 1; i < 4; i++) { + c = fgetc(f); + if (c != trueStr[i] && c != trueStr[i] - 'a' + 'A') { + fprintf( + stderr, + "Unexcepted value at %llu", + ftell(f) / sizeof(char) + ); // 写入报错到标准错误流 + exit(1); + } + } + c = fgetc(f); + if (c != ' ' && c != '\n' && c != ',' && c != ']' && c != '}') { + fprintf( + stderr, + "Unexcepted token %c at %llu", + c, ftell(f) / sizeof(char) + ); // 写入报错到标准错误流 + exit(1); + } + ungetc(c, f); + res->val = JsonStringFromCharArray("true"); + } + else if (c == 'f' || c == 'F') { + // false + const char falseStr[] = "false"; + for (int i = 1; i < 5; i++) { + c = fgetc(f); + if (c != falseStr[i] && c != falseStr[i] - 'a' + 'A') { + fprintf( + stderr, + "Unxcepted token %c at %llu", + c, ftell(f) / sizeof(char) + ); // 写入报错到标准错误流 + exit(1); + } + } + c = fgetc(f); + if (c != ' ' && c != '\n' && c != ',' && c != ']' && c != '}') { + fprintf( + stderr, + "Unxcepted token %c at %llu", + c, ftell(f) / sizeof(char) + ); // 写入报错到标准错误流 + exit(1); + } + ungetc(c, f); + + if (res == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + res->val = JsonStringFromCharArray("false"); + return res; + } + else { + fprintf( + stderr, + "Unexcepted token %c at %llu", + c, ftell(f) / sizeof(char) + ); // 写入报错到标准错误流 + exit(1); + } + return res; +} + + +struct JsonVal* parseObject() { + char c; + struct JsonObj* obj = malloc(sizeof(struct JsonObj)); + struct JsonVal* res = malloc(sizeof(struct JsonVal)); + if (res == NULL) exit(1); + if (obj == NULL) exit(1); + res->type = OBJECT; + + const struct JsonString* keyVal = NULL; + obj->size = 0; + + while ((c = fgetc(f)) != EOF && c != '}') { + if (c == ' ' || c == '\n' || c == '\r' || c == ',') continue; + if (c == '"' || c == '\'') keyVal = parseStringToStr(c); + + else if (c == ':') { + const struct JsonVal* Val = parseValue(); + if(keyVal == NULL) { + fprintf(stderr, "Unexcepted token %c at %llu", c, ftell(f) / sizeof(char)); + exit(1); + } + JsonObjInsert(obj, keyVal, Val); ignoreWhiteCharactor(); + c = fgetc(f); + if(c != ',' && c != '}') { + fprintf(stderr, "Unexcepted token %c at %llu", c, ftell(f) / sizeof(char)); + exit(1); + } + if(c == '}') { + ungetc(c, f); + } + } + else { + fprintf(stderr, "Unexcepted token %c at %llu", c, ftell(f) / sizeof(char)); + exit(1); + } + } + if (c != '}') { + fprintf(stderr, "Unexcepted token EOF at %llu", ftell(f) / sizeof(char)); + exit(1); + } + res->obj = obj; + return res; +} + +struct JsonVal* parseArray() { + struct JsonArray* arr = malloc(sizeof(struct JsonArray)); + struct JsonVal* res = malloc(sizeof(struct JsonVal)); + + if (arr == NULL || res == NULL) exit(1); + res->type = ARRAY; + arr->length = 0; + char c; + ignoreWhiteCharactor(f); + + while ((c = fgetc(f)) != EOF && c != ']') { + ignoreWhiteCharactor(); + if (c != ',') ungetc(c, f); + struct JsonVal* val = parseValue(); + JsonArrayPushBack(arr, val); + + ignoreWhiteCharactor(); + } + if (c != ']') { + fprintf(stderr, "Unexcepted token EOF at %llu", ftell(f) / sizeof(char)); + exit(1); + } + res->arr = arr; + return res; +} + +struct JsonVal* parseNull() { + const char nullStr[] = "null"; + char c; + for (int i = 0; i < 4; i++) { + c = fgetc(f); + if (c != nullStr[i] && c != nullStr[i] - 'a' + 'A') { + fprintf( + stderr, + "Unexcepted token %c at %llu", + c, ftell(f) / sizeof(char) + ); // 写入报错到标准错误流 + exit(1); + } + } + c = fgetc(f); + if (c != ' ' && c != '\n' && c != ',' && c != ']' && c != '}') { + fprintf( + stderr, + "Unexcepted token %c at %llu", + c, ftell(f) / sizeof(char) + ); // 写入报错到标准错误流 + exit(1); + } + ungetc(c, f); + struct JsonVal* res = (struct JsonVal*)malloc(sizeof(struct JsonVal)); + if (res == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + res->type = NONE; res->val = NULL; + return res; +} diff --git a/core/parser/parser.h b/core/parser/parser.h index 32ab232..6ec4360 100644 --- a/core/parser/parser.h +++ b/core/parser/parser.h @@ -1,12 +1,12 @@ -#pragma once -#include "../Json.h" - - -void setInputStream(FILE* stream); -struct JsonVal* parseString(char token); -struct JsonVal* parseNumber(); -struct JsonVal* parseBool(); -struct JsonVal* parseNull(); -struct JsonVal* parseArray(); -struct JsonVal* parseObject(); +#pragma once +#include "../Json.h" + + +void setInputStream(FILE* stream); +struct JsonVal* parseString(char token); +struct JsonVal* parseNumber(); +struct JsonVal* parseBool(); +struct JsonVal* parseNull(); +struct JsonVal* parseArray(); +struct JsonVal* parseObject(); struct JsonVal* parseValue(); \ No newline at end of file diff --git a/core/types/JsonArray.c b/core/types/JsonArray.c index 92665d2..fd562ce 100644 --- a/core/types/JsonArray.c +++ b/core/types/JsonArray.c @@ -1,54 +1,54 @@ -#include "JsonArray.h" - -#include - -struct JsonArray* JsonArrayFromArray(struct JsonVal* arr, size_t length) -{ - struct JsonArray* res = (struct JsonArray*)malloc(sizeof(struct JsonArray)); - if (res == NULL) { // From JsonString - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - res->length = length; - res->arr =(struct JsonVal* ) malloc(sizeof(struct JsonVal) * length); - if (res->arr == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - if (arr != NULL) { - // 深拷贝 arr后续是否会被析构未知 - for (size_t i = 0; i < length; i++) (res->arr)[i] = arr[i]; - } - - return res; -} - -struct JsonArray* JsonArrayNew() -{ - struct JsonArray* arr = (struct JsonArray*)malloc(sizeof(struct JsonArray)); - if (arr == NULL) { // From JsonString - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - arr->length = 10; arr->arr =(struct JsonVal*) malloc(sizeof(struct JsonVal)); - return arr; -} - - -void JsonArrayPushBack(struct JsonArray* arr, struct JsonVal* val) { - arr->length++; - struct JsonVal* tempArr = (struct JsonVal*)malloc(sizeof(struct JsonArray) * arr->length); - if (tempArr == NULL) exit(1); - for (size_t i = 0; i < arr->length - 1; i++) tempArr[i] = arr->arr[i]; - arr->arr = tempArr; - arr->arr[arr->length - 1] = *val; -} - -void destoryJsonArray(struct JsonArray* arr) { - if (arr == NULL) return; - if(arr->arr != NULL) free(arr->arr); // Avoid double free - free(arr); -} +#include "JsonArray.h" + +#include + +struct JsonArray* JsonArrayFromArray(struct JsonVal* arr, size_t length) +{ + struct JsonArray* res = (struct JsonArray*)malloc(sizeof(struct JsonArray)); + if (res == NULL) { // From JsonString + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + res->length = length; + res->arr =(struct JsonVal* ) malloc(sizeof(struct JsonVal) * length); + if (res->arr == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + if (arr != NULL) { + // 深拷贝 arr后续是否会被析构未知 + for (size_t i = 0; i < length; i++) (res->arr)[i] = arr[i]; + } + + return res; +} + +struct JsonArray* JsonArrayNew() +{ + struct JsonArray* arr = (struct JsonArray*)malloc(sizeof(struct JsonArray)); + if (arr == NULL) { // From JsonString + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + arr->length = 10; arr->arr =(struct JsonVal*) malloc(sizeof(struct JsonVal)); + return arr; +} + + +void JsonArrayPushBack(struct JsonArray* arr, struct JsonVal* val) { + arr->length++; + struct JsonVal* tempArr = (struct JsonVal*)malloc(sizeof(struct JsonArray) * arr->length); + if (tempArr == NULL) exit(1); + for (size_t i = 0; i < arr->length - 1; i++) tempArr[i] = arr->arr[i]; + arr->arr = tempArr; + arr->arr[arr->length - 1] = *val; +} + +void destoryJsonArray(struct JsonArray* arr) { + if (arr == NULL) return; + if(arr->arr != NULL) free(arr->arr); // Avoid double free + free(arr); +} diff --git a/core/types/JsonArray.h b/core/types/JsonArray.h index 3663bd0..d376030 100644 --- a/core/types/JsonArray.h +++ b/core/types/JsonArray.h @@ -1,15 +1,15 @@ -#pragma once - -#include "JsonValue.h" -#include - -struct JsonArray { - struct JsonVal* arr; - size_t length; -}; - - -struct JsonArray* JsonArrayFromArray(struct JsonVal* arr, size_t length); -struct JsonArray* JsonArrayNew(); -void JsonArrayPushBack(struct JsonArray* arr, struct JsonVal* val); +#pragma once + +#include "JsonValue.h" +#include + +struct JsonArray { + struct JsonVal* arr; + size_t length; +}; + + +struct JsonArray* JsonArrayFromArray(struct JsonVal* arr, size_t length); +struct JsonArray* JsonArrayNew(); +void JsonArrayPushBack(struct JsonArray* arr, struct JsonVal* val); void destoryJsonArray(struct JsonArray* arr); \ No newline at end of file diff --git a/core/types/JsonObject.c b/core/types/JsonObject.c index 9c70449..d304d10 100644 --- a/core/types/JsonObject.c +++ b/core/types/JsonObject.c @@ -1,29 +1,29 @@ -#include "JsonObject.h" -#include - -void JsonObjInsert( - struct JsonObj* obj, - const struct JsonString* key, - const struct JsonVal* value) { - obj->size++; - struct JsonString* tempKey = malloc(obj->size * sizeof(struct JsonString)); - if (tempKey == NULL) exit(1); - for (int i = 0; i < obj->size - 1; i++) { - tempKey[i] = *(obj->key + i); - //destoryJsonString(obj->key + i); - } - struct JsonVal* tempVal = malloc(obj->size * sizeof(struct JsonVal)); - if (tempVal == NULL) exit(1); - for (int i = 0; i < obj->size - 1; i++) { - tempVal[i] = *(obj->value + i); - } - // destoryJsonVal(obj->value); - tempVal[obj->size - 1] = *value; - tempKey[obj->size - 1] = *key; - obj->key = tempKey; obj->value = tempVal; -} - -void destoryJsonObj(struct JsonObj* obj) { - if(obj->key != NULL) destoryJsonString(obj->key); - if(obj->value != NULL) destoryJsonVal(obj->value); +#include "JsonObject.h" +#include + +void JsonObjInsert( + struct JsonObj* obj, + const struct JsonString* key, + const struct JsonVal* value) { + obj->size++; + struct JsonString* tempKey = malloc(obj->size * sizeof(struct JsonString)); + if (tempKey == NULL) exit(1); + for (int i = 0; i < obj->size - 1; i++) { + tempKey[i] = *(obj->key + i); + //destoryJsonString(obj->key + i); + } + struct JsonVal* tempVal = malloc(obj->size * sizeof(struct JsonVal)); + if (tempVal == NULL) exit(1); + for (int i = 0; i < obj->size - 1; i++) { + tempVal[i] = *(obj->value + i); + } + // destoryJsonVal(obj->value); + tempVal[obj->size - 1] = *value; + tempKey[obj->size - 1] = *key; + obj->key = tempKey; obj->value = tempVal; +} + +void destoryJsonObj(struct JsonObj* obj) { + if(obj->key != NULL) destoryJsonString(obj->key); + if(obj->value != NULL) destoryJsonVal(obj->value); } \ No newline at end of file diff --git a/core/types/JsonObject.h b/core/types/JsonObject.h index 2c07611..311b9c6 100644 --- a/core/types/JsonObject.h +++ b/core/types/JsonObject.h @@ -1,14 +1,14 @@ -#pragma once - -#include "JsonString.h" -#include "JsonValue.h" - -struct JsonObj { - size_t size; - struct JsonString* key; - struct JsonVal* value; -}; - - -void JsonObjInsert(struct JsonObj* obj, const struct JsonString* key, const struct JsonVal* value); +#pragma once + +#include "JsonString.h" +#include "JsonValue.h" + +struct JsonObj { + size_t size; + struct JsonString* key; + struct JsonVal* value; +}; + + +void JsonObjInsert(struct JsonObj* obj, const struct JsonString* key, const struct JsonVal* value); void destoryJsonObj(struct JsonObj* obj); \ No newline at end of file diff --git a/core/types/JsonString.c b/core/types/JsonString.c index 82c1191..ec3d853 100644 --- a/core/types/JsonString.c +++ b/core/types/JsonString.c @@ -1,131 +1,131 @@ -#include "JsonString.h" - -#include -#include -#include -#include - - -struct JsonString* JsonStringFromCharArray(const char* str) { - const size_t strlength = strlen(str); - if (!strlength) { - // 空字符串 - return JsonString_New(); - } - struct JsonString* res = (struct JsonString*) malloc(sizeof(struct JsonString)); - if (res == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - res->capacity = strlength + 1; - res->length = strlength; - res->str = (char*)malloc(sizeof(char) * res->capacity); - if (res->str == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - strncpy(res->str, str, strlength); - res->str[strlength] = 0; - return res; -} - -struct JsonString* JsonStringFromChar(const char c) -{ - struct JsonString* res = (struct JsonString*)malloc(sizeof(struct JsonString)); - if (res == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - res->capacity = 10; - res->length = 1; - res->str = (char*)malloc(sizeof(char) * res->capacity); - if (res->str == NULL) { - // 这逼玩意最后必须要封装出来 - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - sprintf(res->str, "%c", c); - - return res; -} - -struct JsonString* JsonString_New() { - struct JsonString* res = malloc(sizeof(struct JsonString)); - if (res == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - res -> capacity = 10; - res -> length = 0; - res -> str = (char*)malloc(sizeof(char) * res->capacity); - if (res->str == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - (res->str)[0] = 0; - return res; -} - -/// -/// 将字符串切片char[start: end)转换为生成JsonString类型。 -/// end指针于C++STL迭代器.end()相同, 指向位置将不纳入JsonString范围 -/// 长度为end - start + 1;(末尾补0) -/// -/// 起始位置指针 -/// 末尾位置后一位的指针 -/// struct JsonString* - -struct JsonString* JsonStringFromCharArraySlice(char* start, const char* end) { - size_t length = 0; - for (char* s = start; s != end; s++) length++; length++;// 末尾补零用 - struct JsonString* res = malloc(sizeof(struct JsonString)); - if (res == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - res->capacity = length; res->length = length - 1; - res->str = (char*)malloc(sizeof(char) * length); - if (res->str == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - char* writer = res->str; // 单独声明, 后续方便补零 - for (char* reader = start; reader != end; reader++, writer++) - *writer = *reader; - *writer = 0; // for循环中已自增至字符串未应补0处 - return res; -} - - - -void JsonStringPushBackChar(const char c, struct JsonString* str) { - if (str->length + 2 > str->capacity) { - str->capacity = str->length + 5; - if (str->str == NULL) { - // 野指针 - // 异常退出, OS进行内存回收 - exit(1); - } - str -> str = (char*) realloc(str->str, sizeof(char) * str->capacity); - if (str->str == NULL) { - // 内存分配失败 OOM (?) - // 异常退出, OS进行内存回收 - exit(1); - } - } - str->str[str->length] = c; str->str[str->length + 1] = 0; - str->length++; -} - - -void destoryJsonString(struct JsonString* str) { - free(str->str); free(str); +#include "JsonString.h" + +#include +#include +#include +#include + + +struct JsonString* JsonStringFromCharArray(const char* str) { + const size_t strlength = strlen(str); + if (!strlength) { + // 空字符串 + return JsonString_New(); + } + struct JsonString* res = (struct JsonString*) malloc(sizeof(struct JsonString)); + if (res == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + res->capacity = strlength + 1; + res->length = strlength; + res->str = (char*)malloc(sizeof(char) * res->capacity); + if (res->str == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + strncpy(res->str, str, strlength); + res->str[strlength] = 0; + return res; +} + +struct JsonString* JsonStringFromChar(const char c) +{ + struct JsonString* res = (struct JsonString*)malloc(sizeof(struct JsonString)); + if (res == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + res->capacity = 10; + res->length = 1; + res->str = (char*)malloc(sizeof(char) * res->capacity); + if (res->str == NULL) { + // 这逼玩意最后必须要封装出来 + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + sprintf(res->str, "%c", c); + + return res; +} + +struct JsonString* JsonString_New() { + struct JsonString* res = malloc(sizeof(struct JsonString)); + if (res == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + res -> capacity = 10; + res -> length = 0; + res -> str = (char*)malloc(sizeof(char) * res->capacity); + if (res->str == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + (res->str)[0] = 0; + return res; +} + +/// +/// 将字符串切片char[start: end)转换为生成JsonString类型。 +/// end指针于C++STL迭代器.end()相同, 指向位置将不纳入JsonString范围 +/// 长度为end - start + 1;(末尾补0) +/// +/// 起始位置指针 +/// 末尾位置后一位的指针 +/// struct JsonString* + +struct JsonString* JsonStringFromCharArraySlice(char* start, const char* end) { + size_t length = 0; + for (char* s = start; s != end; s++) length++; length++;// 末尾补零用 + struct JsonString* res = malloc(sizeof(struct JsonString)); + if (res == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + res->capacity = length; res->length = length - 1; + res->str = (char*)malloc(sizeof(char) * length); + if (res->str == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + char* writer = res->str; // 单独声明, 后续方便补零 + for (char* reader = start; reader != end; reader++, writer++) + *writer = *reader; + *writer = 0; // for循环中已自增至字符串未应补0处 + return res; +} + + + +void JsonStringPushBackChar(const char c, struct JsonString* str) { + if (str->length + 2 > str->capacity) { + str->capacity = str->length + 5; + if (str->str == NULL) { + // 野指针 + // 异常退出, OS进行内存回收 + exit(1); + } + str -> str = (char*) realloc(str->str, sizeof(char) * str->capacity); + if (str->str == NULL) { + // 内存分配失败 OOM (?) + // 异常退出, OS进行内存回收 + exit(1); + } + } + str->str[str->length] = c; str->str[str->length + 1] = 0; + str->length++; +} + + +void destoryJsonString(struct JsonString* str) { + free(str->str); free(str); } \ No newline at end of file diff --git a/core/types/JsonString.h b/core/types/JsonString.h index c7af8b2..ee6f8c2 100644 --- a/core/types/JsonString.h +++ b/core/types/JsonString.h @@ -1,18 +1,18 @@ -#pragma once -#include - - -struct JsonString { - char* str; - size_t length; - size_t capacity; -}; - - -struct JsonString* JsonStringFromCharArray(const char* str); -struct JsonString* JsonStringFromChar(char c); -struct JsonString* JsonStringFromCharArraySlice(char* start, const char* end); -struct JsonString* JsonString_New(); - -void JsonStringPushBackChar(char c, struct JsonString* str); -void destoryJsonString(struct JsonString* str); +#pragma once +#include + + +struct JsonString { + char* str; + size_t length; + size_t capacity; +}; + + +struct JsonString* JsonStringFromCharArray(const char* str); +struct JsonString* JsonStringFromChar(char c); +struct JsonString* JsonStringFromCharArraySlice(char* start, const char* end); +struct JsonString* JsonString_New(); + +void JsonStringPushBackChar(char c, struct JsonString* str); +void destoryJsonString(struct JsonString* str); diff --git a/core/types/JsonValue.c b/core/types/JsonValue.c index 8d808d8..74c4ec2 100644 --- a/core/types/JsonValue.c +++ b/core/types/JsonValue.c @@ -1,25 +1,25 @@ -#include "JsonValue.h" -#include "JsonString.h" -#include "JsonArray.h" -#include "JsonObject.h" -#include "../utils/outputer.h" - -#include - -void destoryJsonVal(struct JsonVal* val) { - switch (val->type) - { - case NUMBER: - case STRING: - case NONE: - case BOOL: - destoryJsonString(val->val); break; - case OBJECT: - destoryJsonObj(val->obj); break; - case ARRAY: - destoryJsonArray(val->arr); break; - default: - break; - } - free(val); +#include "JsonValue.h" +#include "JsonString.h" +#include "JsonArray.h" +#include "JsonObject.h" +#include "../utils/outputer.h" + +#include + +void destoryJsonVal(struct JsonVal* val) { + switch (val->type) + { + case NUMBER: + case STRING: + case NONE: + case BOOL: + destoryJsonString(val->val); break; + case OBJECT: + destoryJsonObj(val->obj); break; + case ARRAY: + destoryJsonArray(val->arr); break; + default: + break; + } + free(val); } \ No newline at end of file diff --git a/core/types/JsonValue.h b/core/types/JsonValue.h index 258840e..12c6d70 100644 --- a/core/types/JsonValue.h +++ b/core/types/JsonValue.h @@ -1,34 +1,34 @@ -#pragma once - -#include "JsonArray.h" -#include "JsonObject.h" -#include "JsonString.h" - -typedef enum { - STRING, - NUMBER, - BOOL, - ARRAY, - OBJECT, - NONE -} JsonType; - -/// -/// Json对象值 -/// char* val 包含String, Number, None, Bool类型 -/// 因为仅需解析并格式化,压缩及语法检查功能, 后续无数值改动等内容, -/// 于是使用字符串表示实现Number等类型, 减少后期开发压力, 方便存储值 -/// 否则Json因JavaScript自带高精,JSON对象不限制Number大小及精度。导致JSON中Number需自行实现高精 -/// Type定义见JsonType, 用于判定格式并使用对应方法输出 -/// -struct JsonVal { - JsonType type; - union { - struct JsonString* val; // String, Number, NONE, BOOL - struct JsonArray* arr; - struct JsonObj* obj; - }; -}; - - -void destoryJsonVal(struct JsonVal* val); +#pragma once + +#include "JsonArray.h" +#include "JsonObject.h" +#include "JsonString.h" + +typedef enum { + STRING, + NUMBER, + BOOL, + ARRAY, + OBJECT, + NONE +} JsonType; + +/// +/// Json对象值 +/// char* val 包含String, Number, None, Bool类型 +/// 因为仅需解析并格式化,压缩及语法检查功能, 后续无数值改动等内容, +/// 于是使用字符串表示实现Number等类型, 减少后期开发压力, 方便存储值 +/// 否则Json因JavaScript自带高精,JSON对象不限制Number大小及精度。导致JSON中Number需自行实现高精 +/// Type定义见JsonType, 用于判定格式并使用对应方法输出 +/// +struct JsonVal { + JsonType type; + union { + struct JsonString* val; // String, Number, NONE, BOOL + struct JsonArray* arr; + struct JsonObj* obj; + }; +}; + + +void destoryJsonVal(struct JsonVal* val); diff --git a/core/utils/outputer.c b/core/utils/outputer.c index caf49b2..9f38799 100644 --- a/core/utils/outputer.c +++ b/core/utils/outputer.c @@ -1,135 +1,135 @@ -#include "outputer.h" -#include - -static FILE *f = 0; // 初始化为空指针 - -void setOutputStream(FILE* stream) { f = stream; } -int max(int a, int b) { return a > b ? a : b; } - -void indent(int hierarchy) { - for (int i = 0; i < max(hierarchy, 0); i++) fprintf(f, " "); - // 四空格缩进 - // Reason: - // 暂无标准 - // Python四空格缩进习惯了 - // XXX: 后续增加其它缩进方式 - // XXX: 实现setIndentation // XXX vs无高亮? -} - -void printfJsonVal(const struct JsonVal* val, const int hierarchy, const int color) { - switch (val->type){ - case NUMBER: - printNumber(val->val, color); break; - case STRING: - printString(val->val, color); break; - case NONE: - printNONE(color); break; - case BOOL: - printBool(val->val, color); break; - case ARRAY: - printfArray(val->arr, hierarchy, color); break; - case OBJECT: - printfObject(val->obj, hierarchy, color); break; - default: - break; - } -} - -void printJsonVal(const struct JsonVal* val, const int color) { - switch (val->type) { - case NUMBER: - printNumber(val->val, color); break; - case STRING: - printString(val->val, color); break; - case NONE: - printNONE(color); break; - case BOOL: - printBool(val->val, color); break; - case ARRAY: - printArray(val->arr, color); break; - case OBJECT: - printObject(val->obj, color); break; - default: - break; - } -} - -void printString(const struct JsonString* str, const int color) { - if(color) fputs(ANSI_COLOR_GREEN, f); - fputc('"', f); - char * reader = str->str; - while (*reader) { - fputc(*reader, f); - reader++; - } - fputc('"', f);if(color) fputs(ANSI_COLOR_RESET, f); - -} - -void printfObject(const struct JsonObj* obj, const int hierarchy, const int color) { - fputs("{\n", f); - for (int i = 0; i < obj->size; i++) { - indent(hierarchy + 1); - if(color) { - fputs(ANSI_COLOR_MAGENTA, f); - printString(obj->key + i, 0); - fputs(ANSI_COLOR_RESET, f); - }else printString(obj->key + i, 0); - fputs(": ", f); printfJsonVal(obj->value + i, hierarchy + 1, color); - if (i != obj->size - 1) fputs(",", f); - fputs("\n", f); - } - indent(hierarchy); fputs("}", f); -} - - - -void printfArray(const struct JsonArray* array, int hierarchy, const int color) { - fputs("[\n", f); - for (int i = 0; i < array->length; i++) { - indent(hierarchy + 1); printfJsonVal(&array->arr[i], hierarchy + 1, color); - if (i != array->length - 1) fputs(",", f); - fputs("\n", f); - } - indent(hierarchy); fputs("]", f); -} - - -void printNumber(const struct JsonString* num, const int color) { - if(color) fputs(ANSI_COLOR_CYAN, f); - fputs(num->str, f); - if(color) fputs(ANSI_COLOR_RESET, f); -} - -void printBool(const struct JsonString* bl, const int color) { - if(color) fputs(ANSI_COLOR_YELLOW, f); - fputs(bl->str, f); - if(color) fputs(ANSI_COLOR_RESET, f); - -} - -void printNONE(const int color) { - if(color) fputs(ANSI_COLOR_YELLOW, f); - fputs("null", f); - if(color) fputs(ANSI_COLOR_RESET, f); -} - -void printObject(const struct JsonObj* obj, const int color){ - fputs("{", f); - for (int i = 0; i < obj->size; i++) { - if(color) { - fputs(ANSI_COLOR_MAGENTA, f); - printString(obj->key + i, 0); - fputs(ANSI_COLOR_RESET, f); - }else printString(obj->key + i, 0); - fputs(": ", f); printJsonVal(obj->value + i, color); - if (i != obj->size - 1) fputs(",", f); - }fputs("}", f); -} -void printArray(const struct JsonArray* array, const int color){ - fputc('[', f); - for (int i = 0; i < array->length; i++) { - printJsonVal(array->arr + i, color); - if (i != array->length - 1) fputc(',', f); - }fputc(']', f); +#include "outputer.h" +#include + +static FILE *f = 0; // 初始化为空指针 + +void setOutputStream(FILE* stream) { f = stream; } +int max(int a, int b) { return a > b ? a : b; } + +void indent(int hierarchy) { + for (int i = 0; i < max(hierarchy, 0); i++) fprintf(f, " "); + // 四空格缩进 + // Reason: + // 暂无标准 + // Python四空格缩进习惯了 + // XXX: 后续增加其它缩进方式 + // XXX: 实现setIndentation // XXX vs无高亮? +} + +void printfJsonVal(const struct JsonVal* val, const int hierarchy, const int color) { + switch (val->type){ + case NUMBER: + printNumber(val->val, color); break; + case STRING: + printString(val->val, color); break; + case NONE: + printNONE(color); break; + case BOOL: + printBool(val->val, color); break; + case ARRAY: + printfArray(val->arr, hierarchy, color); break; + case OBJECT: + printfObject(val->obj, hierarchy, color); break; + default: + break; + } +} + +void printJsonVal(const struct JsonVal* val, const int color) { + switch (val->type) { + case NUMBER: + printNumber(val->val, color); break; + case STRING: + printString(val->val, color); break; + case NONE: + printNONE(color); break; + case BOOL: + printBool(val->val, color); break; + case ARRAY: + printArray(val->arr, color); break; + case OBJECT: + printObject(val->obj, color); break; + default: + break; + } +} + +void printString(const struct JsonString* str, const int color) { + if(color) fputs(ANSI_COLOR_GREEN, f); + fputc('"', f); + char * reader = str->str; + while (*reader) { + fputc(*reader, f); + reader++; + } + fputc('"', f);if(color) fputs(ANSI_COLOR_RESET, f); + +} + +void printfObject(const struct JsonObj* obj, const int hierarchy, const int color) { + fputs("{\n", f); + for (int i = 0; i < obj->size; i++) { + indent(hierarchy + 1); + if(color) { + fputs(ANSI_COLOR_MAGENTA, f); + printString(obj->key + i, 0); + fputs(ANSI_COLOR_RESET, f); + }else printString(obj->key + i, 0); + fputs(": ", f); printfJsonVal(obj->value + i, hierarchy + 1, color); + if (i != obj->size - 1) fputs(",", f); + fputs("\n", f); + } + indent(hierarchy); fputs("}", f); +} + + + +void printfArray(const struct JsonArray* array, int hierarchy, const int color) { + fputs("[\n", f); + for (int i = 0; i < array->length; i++) { + indent(hierarchy + 1); printfJsonVal(&array->arr[i], hierarchy + 1, color); + if (i != array->length - 1) fputs(",", f); + fputs("\n", f); + } + indent(hierarchy); fputs("]", f); +} + + +void printNumber(const struct JsonString* num, const int color) { + if(color) fputs(ANSI_COLOR_CYAN, f); + fputs(num->str, f); + if(color) fputs(ANSI_COLOR_RESET, f); +} + +void printBool(const struct JsonString* bl, const int color) { + if(color) fputs(ANSI_COLOR_YELLOW, f); + fputs(bl->str, f); + if(color) fputs(ANSI_COLOR_RESET, f); + +} + +void printNONE(const int color) { + if(color) fputs(ANSI_COLOR_YELLOW, f); + fputs("null", f); + if(color) fputs(ANSI_COLOR_RESET, f); +} + +void printObject(const struct JsonObj* obj, const int color){ + fputs("{", f); + for (int i = 0; i < obj->size; i++) { + if(color) { + fputs(ANSI_COLOR_MAGENTA, f); + printString(obj->key + i, 0); + fputs(ANSI_COLOR_RESET, f); + }else printString(obj->key + i, 0); + fputs(": ", f); printJsonVal(obj->value + i, color); + if (i != obj->size - 1) fputs(",", f); + }fputs("}", f); +} +void printArray(const struct JsonArray* array, const int color){ + fputc('[', f); + for (int i = 0; i < array->length; i++) { + printJsonVal(array->arr + i, color); + if (i != array->length - 1) fputc(',', f); + }fputc(']', f); } \ No newline at end of file diff --git a/core/utils/outputer.h b/core/utils/outputer.h index 72d9034..3b36817 100644 --- a/core/utils/outputer.h +++ b/core/utils/outputer.h @@ -1,24 +1,24 @@ -#pragma once -#include "../types/JsonString.h" -#include "../types/JsonValue.h" -#include "../types/JsonArray.h" - -#define ANSI_COLOR_RED "\x1b[31m" -#define ANSI_COLOR_GREEN "\x1b[32m" -#define ANSI_COLOR_YELLOW "\x1b[33m" -#define ANSI_COLOR_BLUE "\x1b[34m" -#define ANSI_COLOR_MAGENTA "\x1b[35m" -#define ANSI_COLOR_CYAN "\x1b[36m" -#define ANSI_COLOR_RESET "\x1b[0m" - -void setOutputStream(FILE* stream); -void printString(const struct JsonString* str, const int color); -void printfJsonVal(const struct JsonVal* val, int hierarchy, const int color); -void printJsonVal(const struct JsonVal* val, const int color); -void printfObject(const struct JsonObj* obj, int hierarchy, const int color); -void printfArray(const struct JsonArray* array, int hierarchy, const int color); -void printNONE(const int color); -void printBool(const struct JsonString* bl, const int color); -void printNumber(const struct JsonString* num, const int color); -void printObject(const struct JsonObj* obj, const int color); +#pragma once +#include "../types/JsonString.h" +#include "../types/JsonValue.h" +#include "../types/JsonArray.h" + +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_BLUE "\x1b[34m" +#define ANSI_COLOR_MAGENTA "\x1b[35m" +#define ANSI_COLOR_CYAN "\x1b[36m" +#define ANSI_COLOR_RESET "\x1b[0m" + +void setOutputStream(FILE* stream); +void printString(const struct JsonString* str, const int color); +void printfJsonVal(const struct JsonVal* val, int hierarchy, const int color); +void printJsonVal(const struct JsonVal* val, const int color); +void printfObject(const struct JsonObj* obj, int hierarchy, const int color); +void printfArray(const struct JsonArray* array, int hierarchy, const int color); +void printNONE(const int color); +void printBool(const struct JsonString* bl, const int color); +void printNumber(const struct JsonString* num, const int color); +void printObject(const struct JsonObj* obj, const int color); void printArray(const struct JsonArray* array, const int color); \ No newline at end of file diff --git a/cutest/CuTest.c b/cutest/CuTest.c index f6d27cd..4b14ce9 100644 --- a/cutest/CuTest.c +++ b/cutest/CuTest.c @@ -1,345 +1,345 @@ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#endif -#include -#include -#include -#include -#include -#include - -#include "CuTest.h" - -/*-------------------------------------------------------------------------* - * CuStr - *-------------------------------------------------------------------------*/ - -char* CuStrAlloc(size_t size) -{ - char* newStr = (char*) malloc( sizeof(char) * (size) ); - return newStr; -} - -char* CuStrCopy(const char* old) -{ - size_t len = strlen(old); - char* newStr = CuStrAlloc(len + 1); - strcpy(newStr, old); - return newStr; -} - -/*-------------------------------------------------------------------------* - * CuString - *-------------------------------------------------------------------------*/ - -void CuStringInit(CuString* str) -{ - str->length = 0; - str->size = STRING_MAX; - str->buffer = (char*) malloc(sizeof(char) * str->size); - str->buffer[0] = '\0'; -} - -CuString* CuStringNew(void) -{ - CuString* str = (CuString*) malloc(sizeof(CuString)); - str->length = 0; - str->size = STRING_MAX; - str->buffer = (char*) malloc(sizeof(char) * str->size); - str->buffer[0] = '\0'; - return str; -} - -void CuStringDelete(CuString *str) -{ - if (!str) return; - free(str->buffer); - free(str); -} - -void CuStringResize(CuString* str, size_t newSize) -{ - str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); - str->size = newSize; -} - -void CuStringAppend(CuString* str, const char* text) -{ - size_t length; - - if (text == NULL) { - text = "NULL"; - } - - length = strlen(text); - if (str->length + length + 1 >= str->size) - CuStringResize(str, str->length + length + 1 + STRING_INC); - str->length += length; - strcat(str->buffer, text); -} - -void CuStringAppendChar(CuString* str, char ch) -{ - char text[2]; - text[0] = ch; - text[1] = '\0'; - CuStringAppend(str, text); -} - -void CuStringAppendFormat(CuString* str, const char* format, ...) -{ - va_list argp; - char buf[HUGE_STRING_LEN]; - va_start(argp, format); - vsprintf(buf, format, argp); - va_end(argp); - CuStringAppend(str, buf); -} - -void CuStringInsert(CuString* str, const char* text, size_t pos) -{ - size_t length = strlen(text); - if (pos > str->length) - pos = str->length; - if (str->length + length + 1 >= str->size) - CuStringResize(str, str->length + length + 1 + STRING_INC); - memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); - str->length += length; - memcpy(str->buffer + pos, text, length); -} - -/*-------------------------------------------------------------------------* - * CuTest - *-------------------------------------------------------------------------*/ - -void CuTestInit(CuTest* t, const char* name, TestFunction function) -{ - t->name = CuStrCopy(name); - t->failed = 0; - t->ran = 0; - t->message = NULL; - t->function = function; - t->jumpBuf = NULL; -} - -CuTest* CuTestNew(const char* name, TestFunction function) -{ - CuTest* tc = CU_ALLOC(CuTest); - CuTestInit(tc, name, function); - return tc; -} - -void CuTestDelete(CuTest *t) -{ - if (!t) return; - CuStringDelete(t->message); - free(t->name); - free(t); -} - -void CuTestRun(CuTest* tc) -{ - jmp_buf buf; - tc->jumpBuf = &buf; - if (setjmp(buf) == 0) - { - tc->ran = 1; - (tc->function)(tc); - } - tc->jumpBuf = 0; -} - -static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) -{ - char buf[HUGE_STRING_LEN]; - - sprintf(buf, "%s:%d: ", file, line); - CuStringInsert(string, buf, 0); - - tc->failed = 1; - free(tc->message); - tc->message = CuStringNew(); - CuStringAppend(tc->message, string->buffer); - if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); -} - -void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) -{ - CuString string; - - CuStringInit(&string); - if (message2 != NULL) - { - CuStringAppend(&string, message2); - CuStringAppend(&string, ": "); - } - CuStringAppend(&string, message); - CuFailInternal(tc, file, line, &string); -} - -void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) -{ - if (condition) return; - CuFail_Line(tc, file, line, NULL, message); -} - -void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, - const char* expected, const char* actual) -{ - CuString string; - if ((expected == NULL && actual == NULL) || - (expected != NULL && actual != NULL && - strcmp(expected, actual) == 0)) - { - return; - } - - CuStringInit(&string); - if (message != NULL) - { - CuStringAppend(&string, message); - CuStringAppend(&string, ": "); - } - CuStringAppend(&string, "expected <"); - CuStringAppend(&string, expected); - CuStringAppend(&string, "> but was <"); - CuStringAppend(&string, actual); - CuStringAppend(&string, ">"); - CuFailInternal(tc, file, line, &string); -} - -void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, - int expected, int actual) -{ - char buf[STRING_MAX]; - if (expected == actual) return; - sprintf(buf, "expected <%d> but was <%d>", expected, actual); - CuFail_Line(tc, file, line, message, buf); -} - -void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, - double expected, double actual, double delta) -{ - char buf[STRING_MAX]; - if (fabs(expected - actual) <= delta) return; - sprintf(buf, "expected <%f> but was <%f>", expected, actual); - - CuFail_Line(tc, file, line, message, buf); -} - -void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, - void* expected, void* actual) -{ - char buf[STRING_MAX]; - if (expected == actual) return; - sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); - CuFail_Line(tc, file, line, message, buf); -} - - -/*-------------------------------------------------------------------------* - * CuSuite - *-------------------------------------------------------------------------*/ - -void CuSuiteInit(CuSuite* testSuite) -{ - testSuite->count = 0; - testSuite->failCount = 0; - memset(testSuite->list, 0, sizeof(testSuite->list)); -} - -CuSuite* CuSuiteNew(void) -{ - CuSuite* testSuite = CU_ALLOC(CuSuite); - CuSuiteInit(testSuite); - return testSuite; -} - -void CuSuiteDelete(CuSuite *testSuite) -{ - unsigned int n; - for (n=0; n < MAX_TEST_CASES; n++) - { - if (testSuite->list[n]) - { - CuTestDelete(testSuite->list[n]); - } - } - free(testSuite); - -} - -void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) -{ - assert(testSuite->count < MAX_TEST_CASES); - testSuite->list[testSuite->count] = testCase; - testSuite->count++; -} - -void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) -{ - int i; - for (i = 0 ; i < testSuite2->count ; ++i) - { - CuTest* testCase = testSuite2->list[i]; - CuSuiteAdd(testSuite, testCase); - } -} - -void CuSuiteRun(CuSuite* testSuite) -{ - int i; - for (i = 0 ; i < testSuite->count ; ++i) - { - CuTest* testCase = testSuite->list[i]; - CuTestRun(testCase); - if (testCase->failed) { testSuite->failCount += 1; } - } -} - -void CuSuiteSummary(CuSuite* testSuite, CuString* summary) -{ - int i; - for (i = 0 ; i < testSuite->count ; ++i) - { - CuTest* testCase = testSuite->list[i]; - CuStringAppend(summary, testCase->failed ? "F" : "."); - } - CuStringAppend(summary, "\n\n"); -} - -void CuSuiteDetails(CuSuite* testSuite, CuString* details) -{ - int i; - int failCount = 0; - - if (testSuite->failCount == 0) - { - int passCount = testSuite->count - testSuite->failCount; - const char* testWord = passCount == 1 ? "test" : "tests"; - CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); - } - else - { - if (testSuite->failCount == 1) - CuStringAppend(details, "There was 1 failure:\n"); - else - CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); - - for (i = 0 ; i < testSuite->count ; ++i) - { - CuTest* testCase = testSuite->list[i]; - if (testCase->failed) - { - failCount++; - CuStringAppendFormat(details, "%d) %s: %s\n", - failCount, testCase->name, testCase->message->buffer); - } - } - CuStringAppend(details, "\n!!!FAILURES!!!\n"); - - CuStringAppendFormat(details, "Runs: %d ", testSuite->count); - CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); - CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); - } -} +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif +#include +#include +#include +#include +#include +#include + +#include "CuTest.h" + +/*-------------------------------------------------------------------------* + * CuStr + *-------------------------------------------------------------------------*/ + +char* CuStrAlloc(size_t size) +{ + char* newStr = (char*) malloc( sizeof(char) * (size) ); + return newStr; +} + +char* CuStrCopy(const char* old) +{ + size_t len = strlen(old); + char* newStr = CuStrAlloc(len + 1); + strcpy(newStr, old); + return newStr; +} + +/*-------------------------------------------------------------------------* + * CuString + *-------------------------------------------------------------------------*/ + +void CuStringInit(CuString* str) +{ + str->length = 0; + str->size = STRING_MAX; + str->buffer = (char*) malloc(sizeof(char) * str->size); + str->buffer[0] = '\0'; +} + +CuString* CuStringNew(void) +{ + CuString* str = (CuString*) malloc(sizeof(CuString)); + str->length = 0; + str->size = STRING_MAX; + str->buffer = (char*) malloc(sizeof(char) * str->size); + str->buffer[0] = '\0'; + return str; +} + +void CuStringDelete(CuString *str) +{ + if (!str) return; + free(str->buffer); + free(str); +} + +void CuStringResize(CuString* str, size_t newSize) +{ + str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); + str->size = newSize; +} + +void CuStringAppend(CuString* str, const char* text) +{ + size_t length; + + if (text == NULL) { + text = "NULL"; + } + + length = strlen(text); + if (str->length + length + 1 >= str->size) + CuStringResize(str, str->length + length + 1 + STRING_INC); + str->length += length; + strcat(str->buffer, text); +} + +void CuStringAppendChar(CuString* str, char ch) +{ + char text[2]; + text[0] = ch; + text[1] = '\0'; + CuStringAppend(str, text); +} + +void CuStringAppendFormat(CuString* str, const char* format, ...) +{ + va_list argp; + char buf[HUGE_STRING_LEN]; + va_start(argp, format); + vsprintf(buf, format, argp); + va_end(argp); + CuStringAppend(str, buf); +} + +void CuStringInsert(CuString* str, const char* text, size_t pos) +{ + size_t length = strlen(text); + if (pos > str->length) + pos = str->length; + if (str->length + length + 1 >= str->size) + CuStringResize(str, str->length + length + 1 + STRING_INC); + memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); + str->length += length; + memcpy(str->buffer + pos, text, length); +} + +/*-------------------------------------------------------------------------* + * CuTest + *-------------------------------------------------------------------------*/ + +void CuTestInit(CuTest* t, const char* name, TestFunction function) +{ + t->name = CuStrCopy(name); + t->failed = 0; + t->ran = 0; + t->message = NULL; + t->function = function; + t->jumpBuf = NULL; +} + +CuTest* CuTestNew(const char* name, TestFunction function) +{ + CuTest* tc = CU_ALLOC(CuTest); + CuTestInit(tc, name, function); + return tc; +} + +void CuTestDelete(CuTest *t) +{ + if (!t) return; + CuStringDelete(t->message); + free(t->name); + free(t); +} + +void CuTestRun(CuTest* tc) +{ + jmp_buf buf; + tc->jumpBuf = &buf; + if (setjmp(buf) == 0) + { + tc->ran = 1; + (tc->function)(tc); + } + tc->jumpBuf = 0; +} + +static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) +{ + char buf[HUGE_STRING_LEN]; + + sprintf(buf, "%s:%d: ", file, line); + CuStringInsert(string, buf, 0); + + tc->failed = 1; + free(tc->message); + tc->message = CuStringNew(); + CuStringAppend(tc->message, string->buffer); + if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); +} + +void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) +{ + CuString string; + + CuStringInit(&string); + if (message2 != NULL) + { + CuStringAppend(&string, message2); + CuStringAppend(&string, ": "); + } + CuStringAppend(&string, message); + CuFailInternal(tc, file, line, &string); +} + +void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) +{ + if (condition) return; + CuFail_Line(tc, file, line, NULL, message); +} + +void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + const char* expected, const char* actual) +{ + CuString string; + if ((expected == NULL && actual == NULL) || + (expected != NULL && actual != NULL && + strcmp(expected, actual) == 0)) + { + return; + } + + CuStringInit(&string); + if (message != NULL) + { + CuStringAppend(&string, message); + CuStringAppend(&string, ": "); + } + CuStringAppend(&string, "expected <"); + CuStringAppend(&string, expected); + CuStringAppend(&string, "> but was <"); + CuStringAppend(&string, actual); + CuStringAppend(&string, ">"); + CuFailInternal(tc, file, line, &string); +} + +void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + int expected, int actual) +{ + char buf[STRING_MAX]; + if (expected == actual) return; + sprintf(buf, "expected <%d> but was <%d>", expected, actual); + CuFail_Line(tc, file, line, message, buf); +} + +void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + double expected, double actual, double delta) +{ + char buf[STRING_MAX]; + if (fabs(expected - actual) <= delta) return; + sprintf(buf, "expected <%f> but was <%f>", expected, actual); + + CuFail_Line(tc, file, line, message, buf); +} + +void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + void* expected, void* actual) +{ + char buf[STRING_MAX]; + if (expected == actual) return; + sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); + CuFail_Line(tc, file, line, message, buf); +} + + +/*-------------------------------------------------------------------------* + * CuSuite + *-------------------------------------------------------------------------*/ + +void CuSuiteInit(CuSuite* testSuite) +{ + testSuite->count = 0; + testSuite->failCount = 0; + memset(testSuite->list, 0, sizeof(testSuite->list)); +} + +CuSuite* CuSuiteNew(void) +{ + CuSuite* testSuite = CU_ALLOC(CuSuite); + CuSuiteInit(testSuite); + return testSuite; +} + +void CuSuiteDelete(CuSuite *testSuite) +{ + unsigned int n; + for (n=0; n < MAX_TEST_CASES; n++) + { + if (testSuite->list[n]) + { + CuTestDelete(testSuite->list[n]); + } + } + free(testSuite); + +} + +void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) +{ + assert(testSuite->count < MAX_TEST_CASES); + testSuite->list[testSuite->count] = testCase; + testSuite->count++; +} + +void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) +{ + int i; + for (i = 0 ; i < testSuite2->count ; ++i) + { + CuTest* testCase = testSuite2->list[i]; + CuSuiteAdd(testSuite, testCase); + } +} + +void CuSuiteRun(CuSuite* testSuite) +{ + int i; + for (i = 0 ; i < testSuite->count ; ++i) + { + CuTest* testCase = testSuite->list[i]; + CuTestRun(testCase); + if (testCase->failed) { testSuite->failCount += 1; } + } +} + +void CuSuiteSummary(CuSuite* testSuite, CuString* summary) +{ + int i; + for (i = 0 ; i < testSuite->count ; ++i) + { + CuTest* testCase = testSuite->list[i]; + CuStringAppend(summary, testCase->failed ? "F" : "."); + } + CuStringAppend(summary, "\n\n"); +} + +void CuSuiteDetails(CuSuite* testSuite, CuString* details) +{ + int i; + int failCount = 0; + + if (testSuite->failCount == 0) + { + int passCount = testSuite->count - testSuite->failCount; + const char* testWord = passCount == 1 ? "test" : "tests"; + CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); + } + else + { + if (testSuite->failCount == 1) + CuStringAppend(details, "There was 1 failure:\n"); + else + CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); + + for (i = 0 ; i < testSuite->count ; ++i) + { + CuTest* testCase = testSuite->list[i]; + if (testCase->failed) + { + failCount++; + CuStringAppendFormat(details, "%d) %s: %s\n", + failCount, testCase->name, testCase->message->buffer); + } + } + CuStringAppend(details, "\n!!!FAILURES!!!\n"); + + CuStringAppendFormat(details, "Runs: %d ", testSuite->count); + CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); + CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); + } +} diff --git a/cutest/CuTest.h b/cutest/CuTest.h index b24919d..1ffb0f8 100644 --- a/cutest/CuTest.h +++ b/cutest/CuTest.h @@ -1,117 +1,117 @@ -#ifndef CU_TEST_H -#define CU_TEST_H - -#include -#include -#include - -#define CUTEST_VERSION "CuTest 1.5c" - -/* CuString */ - -char* CuStrAlloc(size_t size); -char* CuStrCopy(const char* old); - -#define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE))) - -#define HUGE_STRING_LEN 8192 -#define STRING_MAX 256 -#define STRING_INC 256 - -typedef struct -{ - size_t length; - size_t size; - char* buffer; -} CuString; - -void CuStringInit(CuString* str); -CuString* CuStringNew(void); -void CuStringRead(CuString* str, const char* path); -void CuStringAppend(CuString* str, const char* text); -void CuStringAppendChar(CuString* str, char ch); -void CuStringAppendFormat(CuString* str, const char* format, ...); -void CuStringInsert(CuString* str, const char* text, size_t pos); -void CuStringResize(CuString* str, size_t newSize); -void CuStringDelete(CuString* str); - -/* CuTest */ - -typedef struct CuTest CuTest; - -typedef void (*TestFunction)(CuTest *); - -struct CuTest -{ - char* name; - TestFunction function; - int failed; - int ran; - CuString *message; - jmp_buf *jumpBuf; -}; - -void CuTestInit(CuTest* t, const char* name, TestFunction function); -CuTest* CuTestNew(const char* name, TestFunction function); -void CuTestRun(CuTest* tc); -void CuTestDelete(CuTest *t); - -/* Internal versions of assert functions -- use the public versions */ -void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); -void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); -void CuAssertStrEquals_LineMsg(CuTest* tc, - const char* file, int line, const char* message, - const char* expected, const char* actual); -void CuAssertIntEquals_LineMsg(CuTest* tc, - const char* file, int line, const char* message, - int expected, int actual); -void CuAssertDblEquals_LineMsg(CuTest* tc, - const char* file, int line, const char* message, - double expected, double actual, double delta); -void CuAssertPtrEquals_LineMsg(CuTest* tc, - const char* file, int line, const char* message, - void* expected, void* actual); - -/* public assert functions */ - -#define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms)) -#define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) -#define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) - -#define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) -#define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) -#define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) -#define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) -#define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) -#define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl)) -#define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) -#define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) - -#define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",((p) != NULL)) -#define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),((p) != NULL)) - -/* CuSuite */ - -#define MAX_TEST_CASES 1024 - -#define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) - -typedef struct -{ - int count; - CuTest* list[MAX_TEST_CASES]; - int failCount; - -} CuSuite; - - -void CuSuiteInit(CuSuite* testSuite); -CuSuite* CuSuiteNew(void); -void CuSuiteDelete(CuSuite *testSuite); -void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase); -void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); -void CuSuiteRun(CuSuite* testSuite); -void CuSuiteSummary(CuSuite* testSuite, CuString* summary); -void CuSuiteDetails(CuSuite* testSuite, CuString* details); - -#endif /* CU_TEST_H */ +#ifndef CU_TEST_H +#define CU_TEST_H + +#include +#include +#include + +#define CUTEST_VERSION "CuTest 1.5c" + +/* CuString */ + +char* CuStrAlloc(size_t size); +char* CuStrCopy(const char* old); + +#define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE))) + +#define HUGE_STRING_LEN 8192 +#define STRING_MAX 256 +#define STRING_INC 256 + +typedef struct +{ + size_t length; + size_t size; + char* buffer; +} CuString; + +void CuStringInit(CuString* str); +CuString* CuStringNew(void); +void CuStringRead(CuString* str, const char* path); +void CuStringAppend(CuString* str, const char* text); +void CuStringAppendChar(CuString* str, char ch); +void CuStringAppendFormat(CuString* str, const char* format, ...); +void CuStringInsert(CuString* str, const char* text, size_t pos); +void CuStringResize(CuString* str, size_t newSize); +void CuStringDelete(CuString* str); + +/* CuTest */ + +typedef struct CuTest CuTest; + +typedef void (*TestFunction)(CuTest *); + +struct CuTest +{ + char* name; + TestFunction function; + int failed; + int ran; + CuString *message; + jmp_buf *jumpBuf; +}; + +void CuTestInit(CuTest* t, const char* name, TestFunction function); +CuTest* CuTestNew(const char* name, TestFunction function); +void CuTestRun(CuTest* tc); +void CuTestDelete(CuTest *t); + +/* Internal versions of assert functions -- use the public versions */ +void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); +void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); +void CuAssertStrEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + const char* expected, const char* actual); +void CuAssertIntEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + int expected, int actual); +void CuAssertDblEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + double expected, double actual, double delta); +void CuAssertPtrEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + void* expected, void* actual); + +/* public assert functions */ + +#define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms)) +#define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) +#define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) + +#define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) +#define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) +#define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) +#define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl)) +#define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) + +#define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",((p) != NULL)) +#define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),((p) != NULL)) + +/* CuSuite */ + +#define MAX_TEST_CASES 1024 + +#define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) + +typedef struct +{ + int count; + CuTest* list[MAX_TEST_CASES]; + int failCount; + +} CuSuite; + + +void CuSuiteInit(CuSuite* testSuite); +CuSuite* CuSuiteNew(void); +void CuSuiteDelete(CuSuite *testSuite); +void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase); +void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); +void CuSuiteRun(CuSuite* testSuite); +void CuSuiteSummary(CuSuite* testSuite, CuString* summary); +void CuSuiteDetails(CuSuite* testSuite, CuString* details); + +#endif /* CU_TEST_H */ diff --git a/test/stringTest.c b/test/stringTest.c index 46aed81..3720c52 100644 --- a/test/stringTest.c +++ b/test/stringTest.c @@ -1,5 +1,5 @@ -#include "CuTest.h" - -int main() { - +#include "CuTest.h" + +int main() { + } \ No newline at end of file