diff --git a/.gitignore b/.gitignore
index d1a7c86..3b234ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,11 @@
.vs/
+.idea/
x64/
cmake-build-debug/
-*.pdb.idea/
cmake-build-release/
cmake-build-debug-mingw/
+*.pdb
+
+lcui-quick-start.zip
+package-lock.json
+-g/
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 35eb1dd..61b903a 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,6 @@
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2e8ce51..0872886 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,6 +2,9 @@ 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
@@ -19,7 +22,7 @@ add_library(jsonParserLib
core/utils/utf2gbk/UTF2GBK.c
core/utils/utf2gbk/UTF2GBK.h
)
-target_link_libraries(jsonParserLib PRIVATE iconv)
+target_link_libraries(jsonParserLib PRIVATE Iconv::Iconv)
add_executable(json
cli/main.c
diff --git a/cli/main.c b/cli/main.c
index f8ff664..52a36cf 100644
--- a/cli/main.c
+++ b/cli/main.c
@@ -6,78 +6,69 @@
#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文本
-
+ FILE* input; // 杈撳叆娴
+ FILE* output; // 杈撳嚭娴
+ int compress; // 鏄惁鍘嬬缉
+ int format; // 鏄惁鏍煎紡鍖
+ // int utf8Text; // 鏄惁涓簎tf-8 鏂囨湰 鏄垯闇璧勬簮鍥炴敹鏃跺垹闄や腑闂存枃浠
+ // char* convertCacheFilePath; // 涓簎tf-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, ""); // 设置本地化环境以支持宽字符
+ // setlocale(LC_ALL, ""); // 璁剧疆鏈湴鍖栫幆澧冧互鏀寔瀹藉瓧绗
const struct CommandLineArgs args = parseCommandLineArgs(argc, argv);
- // 设置输入输出流
- // 默认为标准输入输出
+ // 璁剧疆杈撳叆杈撳嚭娴
+ // 榛樿涓烘爣鍑嗚緭鍏ヨ緭鍑
setInputStream(args.input);
- setOutputStream(args.output);
-
- //解析Json
+ setOutputStream(args.output);
+
+ //瑙f瀽Json
const struct JsonVal* json = parseValue();
- if (args.compress) {
- printJsonVal(json);
- }
- else if (args.format) {
- printfJsonVal(json, 0);
- }
+ if (args.compress) { printJsonVal(json); }
+ else if (args.format) { printfJsonVal(json, 0); }
//destoryJsonVal(json);
- if (args.input != stdin) {
- fclose(args.input);
- }
+ if (args.input != stdin) { fclose(args.input); }
if (args.output != stdout) {
fclose(args.output);
- if(args.utf8Text) {
- convertGbkToUtf8(args.output);
- }
+ // if (args.utf8Text) { convertGbkToUtf8(args.output); }
}
- return 0;
+ 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 = "";
- // 标记是否已经出现了--format或--compress
+ // args.utf8Text = 0;
+ // args.convertCacheFilePath = "__cache.json";
+ // 鏍囪鏄惁宸茬粡鍑虹幇浜--format鎴--compress
int formatSeen = 0;
int compressSeen = 0;
- // 解析命令行参数
+ // 瑙f瀽鍛戒护琛屽弬鏁
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "--output") == 0 || strcmp(argv[i], "-of") == 0) {
- // 指定输出流
+ // 鎸囧畾杈撳嚭娴
if (i + 1 < argc) {
printf("Output: %s\n", argv[i + 1]);
args.output = fopen(argv[i + 1], "w");
- args.outputFilePath = argv[i+1];
+ // args.outputFilePath = argv[i + 1];
if (args.output == NULL) {
perror("Error opening output file");
exit(EXIT_FAILURE);
}
- i++; // 跳过下一个参数,因为它是文件路径
+ i++; // 璺宠繃涓嬩竴涓弬鏁帮紝鍥犱负瀹冩槸鏂囦欢璺緞
}
else {
fprintf(stderr, "Error: --output option requires a file path.\n");
@@ -85,22 +76,22 @@ struct CommandLineArgs parseCommandLineArgs(int argc, char* argv[]) {
}
}
else if (strcmp(argv[i], "--input") == 0 || strcmp(argv[i], "-if") == 0) {
- // 指定输入流
+ // 鎸囧畾杈撳叆娴
if (i + 1 < argc) {
- FILE* f = fopen(argv[i + 1], "r");
- args.convertCacheFilePath = "__cache.json";
- if(isUtf8(f)) {
- printf("INFO: Is UTF-8 Text\n");
- args.input = convertUtf8ToGbk(f,args.convertCacheFilePath);
- args.utf8Text = 1;
- }else {
- args.input = fopen(argv[i + 1], "r");
- }
+ 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++; // 跳过下一个参数,因为它是文件路径
+ i++; // 璺宠繃涓嬩竴涓弬鏁帮紝鍥犱负瀹冩槸鏂囦欢璺緞
}
else {
fprintf(stderr, "Error: --input option requires a file path.\n");
@@ -108,7 +99,7 @@ struct CommandLineArgs parseCommandLineArgs(int argc, char* argv[]) {
}
}
else if (strcmp(argv[i], "--compress") == 0 || strcmp(argv[i], "-c") == 0) {
- // 压缩格式输出Json
+ // 鍘嬬缉鏍煎紡杈撳嚭Json
if (formatSeen) {
fprintf(stderr, "Error: --compress and --format cannot be used together.\n");
exit(EXIT_FAILURE);
@@ -118,7 +109,7 @@ struct CommandLineArgs parseCommandLineArgs(int argc, char* argv[]) {
compressSeen = 1;
}
else if (strcmp(argv[i], "--format") == 0 || strcmp(argv[i], "-f") == 0) {
- // 格式化输出Json
+ // 鏍煎紡鍖栬緭鍑篔son
if (compressSeen) {
fprintf(stderr, "Error: --compress and --format cannot be used together.\n");
exit(EXIT_FAILURE);
@@ -127,23 +118,23 @@ struct CommandLineArgs parseCommandLineArgs(int argc, char* argv[]) {
formatSeen = 1;
}
else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
- printf("用法:json [选项]...\n");
- printf("从输入中解析和格式化JSON数据,可选择压缩或格式化输出。\n\n");
+ printf("鐢ㄦ硶锛歫son [閫夐」]...\n");
+ printf("浠庤緭鍏ヤ腑瑙f瀽鍜屾牸寮忓寲JSON鏁版嵁锛屽彲閫夋嫨鍘嬬缉鎴栨牸寮忓寲杈撳嚭銆俓n\n");
- printf("长选项的强制性参数对于短选项也是强制性的。\n");
- printf(" -if, --input 指定输入文件(默认为标准输入)\n");
- printf(" -of, --output 指定输出文件(默认为标准输出)\n");
- printf(" -f, --format 使用树形缩进输出格式化的JSON\n");
- printf(" -c, --compress 输出压缩的JSON\n");
- printf(" -h, --help 显示此帮助并退出\n\n");
+ printf("闀块夐」鐨勫己鍒舵у弬鏁板浜庣煭閫夐」涔熸槸寮哄埗鎬х殑銆俓n");
+ printf(" -if, --input 鎸囧畾杈撳叆鏂囦欢锛堥粯璁や负鏍囧噯杈撳叆锛塡n");
+ printf(" -of, --output 鎸囧畾杈撳嚭鏂囦欢锛堥粯璁や负鏍囧噯杈撳嚭锛塡n");
+ printf(" -f, --format 浣跨敤鏍戝舰缂╄繘杈撳嚭鏍煎紡鍖栫殑JSON\n");
+ printf(" -c, --compress 杈撳嚭鍘嬬缉鐨凧SON\n");
+ printf(" -h, --help 鏄剧ず姝ゅ府鍔╁苟閫鍑篭n\n");
- printf("示例:\n");
+ printf("绀轰緥锛歕n");
printf(" json -if input.json -of output.json -f\n");
printf(" json --input=input.json --output=output.json --compress\n\n");
- printf("如果未指定输入或输出文件,则程序将默认使用标准输入或标准输出。\n\n");
+ printf("濡傛灉鏈寚瀹氳緭鍏ユ垨杈撳嚭鏂囦欢锛屽垯绋嬪簭灏嗛粯璁や娇鐢ㄦ爣鍑嗚緭鍏ユ垨鏍囧噯杈撳嚭銆俓n\n");
- printf("注意:--compress 和 --format 选项不能同时使用。\n");
+ printf("娉ㄦ剰锛--compress 鍜 --format 閫夐」涓嶈兘鍚屾椂浣跨敤銆俓n");
exit(0);
}
else {
@@ -153,4 +144,4 @@ struct CommandLineArgs parseCommandLineArgs(int argc, char* argv[]) {
}
return args;
-}
\ No newline at end of file
+}
diff --git a/core/parser/parser.c b/core/parser/parser.c
index a23c23e..fcdcdd3 100644
--- a/core/parser/parser.c
+++ b/core/parser/parser.c
@@ -30,7 +30,7 @@ struct JsonVal* parseValue() {
ungetc(c, f);
return parseNumber();
}
- if (c == '"' || c == '\'') return parseString();
+ if (c == '"' || c == '\'') return parseString(c);
fprintf(
stderr,
"Unexcepted token %c at %llu",
@@ -39,12 +39,12 @@ struct JsonVal* parseValue() {
exit(1);
}
-struct JsonString* parseStringToStr() {
+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 != '"' && c != '\'') {
+ while ((c = fgetc(f)) && c != EOF && c != token) {
if (c == '\\') {
c = fgetc(f);
if (c == EOF) {
@@ -75,15 +75,15 @@ struct JsonString* parseStringToStr() {
else { JsonStringPushBackChar(c, str); }
}
- if (c != '"' && c != '\'') {
- fprintf(stderr, "Expected character \" or ', but got EOF.\tString value parse begin with %llu\n", pos);
+ 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() {
- struct JsonString* str = parseStringToStr();
+struct JsonVal* parseString(char token) {
+ struct JsonString* str = parseStringToStr(token);
struct JsonVal* res = malloc(sizeof(struct JsonVal));
if (res == NULL) {
@@ -234,7 +234,7 @@ struct JsonVal* parseObject() {
while ((c = fgetc(f)) != EOF && c != '}') {
if (c == ' ' || c == '\n' || c == '\r' || c == ',') continue;
- if (c == '"' || c == '\'') keyVal = parseStringToStr();
+ if (c == '"' || c == '\'') keyVal = parseStringToStr(c);
else if (c == ':') {
const struct JsonVal* Val = parseValue();
diff --git a/core/parser/parser.h b/core/parser/parser.h
index 6f45355..6ec4360 100644
--- a/core/parser/parser.h
+++ b/core/parser/parser.h
@@ -3,7 +3,7 @@
void setInputStream(FILE* stream);
-struct JsonVal* parseString();
+struct JsonVal* parseString(char token);
struct JsonVal* parseNumber();
struct JsonVal* parseBool();
struct JsonVal* parseNull();
diff --git a/core/utils/utf2gbk/UTF2GBK.c b/core/utils/utf2gbk/UTF2GBK.c
index 1954c41..3cf9f9e 100644
--- a/core/utils/utf2gbk/UTF2GBK.c
+++ b/core/utils/utf2gbk/UTF2GBK.c
@@ -1,17 +1,21 @@
+#define _POSIX_C_SOURCE 200112L
+
#include
#include
#include
#include
+#include
+
+#define BUFFER_SIZE 4096
-FILE* convertUtf8ToGbk(FILE* input, const char* outputFileName) {
+FILE* convertUtf8ToGbk(FILE* input) {
iconv_t cd;
+ FILE* output = tmpfile();
cd = iconv_open("GBK", "UTF-8");
if (cd == (iconv_t)-1) {
perror("iconv_open");
exit(EXIT_FAILURE);
}
-
- FILE* output = fopen(outputFileName, "w");
if (output == NULL) {
perror("fopen");
exit(EXIT_FAILURE);
@@ -39,9 +43,9 @@ FILE* convertUtf8ToGbk(FILE* input, const char* outputFileName) {
iconv_close(cd);
fclose(input);
- fclose(output);
+ rewind(output);
- return fopen(outputFileName, "r");
+ return output;
}
void convertGbkToUtf8(FILE* file) {
@@ -92,9 +96,9 @@ void convertGbkToUtf8(FILE* file) {
iconv_close(cd);
// Reopen the original file for writing
- file = fopen("converted_file.txt", "w");
+ file = freopen("converted_file.txt", "w", stdout);
if (file == NULL) {
- perror("fopen");
+ perror("freopen");
exit(EXIT_FAILURE);
}
@@ -109,26 +113,21 @@ void convertGbkToUtf8(FILE* file) {
int isUtf8(FILE* file) {
- rewind(file); // 灏嗘枃浠舵寚閽堝畾浣嶅埌鏂囦欢寮澶
-
+ // 鑾峰彇褰撳墠鏂囦欢鎸囬拡浣嶇疆
+ long originalPosition = ftell(file);
+ int res = 0;
// 璇诲彇鏂囦欢鐨勫墠涓変釜瀛楄妭
char bom[3];
size_t bytesRead = fread(bom, 1, 3, file);
-
- // 濡傛灉鏂囦欢灏忎簬3涓瓧鑺傦紝杩斿洖0
- if (bytesRead < 3) {
- rewind(file);
- return 0;
- }
+ fseek(file, originalPosition, SEEK_SET);
+ fwrite(bom, 1, bytesRead, file);
// 鍒ゆ柇鏄惁涓篣TF-8 without BOM缂栫爜
if (bom[0] == (char)0xEF && bom[1] == (char)0xBB && bom[2] == (char)0xBF) {
// 鏂囦欢鍖呭惈BOM锛屼笉鏄疷TF-8 without BOM缂栫爜
- rewind(file);
- return 0;
+ res = 0;
} else {
- // 鏂囦欢涓嶅寘鍚獴OM锛屽彲鑳芥槸UTF-8 without BOM缂栫爜
- rewind(file);
- return 1;
+ res = 1;
}
-}
\ No newline at end of file
+ return res;
+}
diff --git a/core/utils/utf2gbk/UTF2GBK.h b/core/utils/utf2gbk/UTF2GBK.h
index dc2a017..c53f639 100644
--- a/core/utils/utf2gbk/UTF2GBK.h
+++ b/core/utils/utf2gbk/UTF2GBK.h
@@ -4,6 +4,6 @@
#pragma once
#include
-FILE* convertUtf8ToGbk(FILE* input, const char* outputFileName);
+FILE* convertUtf8ToGbk(FILE* input);
void convertGbkToUtf8(FILE* input);
int isUtf8(FILE* file);
\ No newline at end of file