jrpc_cmd support parse float and string

This commit is contained in:
Lyon 2024-07-15 17:00:36 +08:00
parent 1c925f4ce5
commit 60500ff427
7 changed files with 250 additions and 45 deletions

View File

@ -261,7 +261,8 @@ void JRPC_server_handle_string(JRPC* self, char* json_str) {
jrpc_free(ack_str); jrpc_free(ack_str);
} }
cJSON** param_array = (cJSON**)jrpc_malloc(param_count * sizeof(cJSON*)); cJSON** param_array =
(cJSON**)jrpc_malloc(param_count * sizeof(cJSON*) + 1);
if (param_array == NULL) { if (param_array == NULL) {
jrpc_debug("Memory allocation failed for param_array\n"); jrpc_debug("Memory allocation failed for param_array\n");
JRPC_send_acknowledgement(self, id->valueint, ACK_MEMORY_ERROR, JRPC_send_acknowledgement(self, id->valueint, ACK_MEMORY_ERROR,
@ -726,17 +727,23 @@ int jrpc_test_server() {
char* jrpc_strtok(char* str, const char* delimiters, char** context) { char* jrpc_strtok(char* str, const char* delimiters, char** context) {
char* start = str ? str : *context; char* start = str ? str : *context;
if (!start) if (!start) {
return NULL; return NULL;
}
while (*start && strchr(delimiters, *start)) // Skip initial delimiters
while (*start && strchr(delimiters, *start)) {
++start; ++start;
if (!*start) }
if (!*start) {
*context = NULL;
return NULL; return NULL;
}
char* end = start; char* end = start;
while (*end && !strchr(delimiters, *end)) while (*end && !strchr(delimiters, *end)) {
++end; ++end;
}
if (*end) { if (*end) {
*end = '\0'; *end = '\0';
@ -748,6 +755,36 @@ char* jrpc_strtok(char* str, const char* delimiters, char** context) {
return start; return start;
} }
static char* extract_quoted_string(const char** input) {
const char* start = *input;
if (*start != '"') {
return NULL;
}
start++;
const char* end = strchr(start, '"');
if (!end) {
return NULL;
}
size_t len = end - start;
char* result = (char*)malloc(len + 1);
if (!result) {
return NULL;
}
strncpy(result, start, len);
result[len] = '\0';
*input = end + 1;
return result;
}
static void skip_whitespace(const char** input) {
if (input == NULL || *input == NULL) {
return;
}
while (**input == ' ' || **input == '\t' || **input == '\n') {
(*input)++;
}
}
char* JRPC_cmd(JRPC* jrpc, const char* cmd) { char* JRPC_cmd(JRPC* jrpc, const char* cmd) {
char* cmd_copy = NULL; char* cmd_copy = NULL;
char* method = NULL; char* method = NULL;
@ -762,8 +799,10 @@ char* JRPC_cmd(JRPC* jrpc, const char* cmd) {
goto __exit; goto __exit;
} }
char* context = NULL; const char* cursor = cmd_copy;
char* token = jrpc_strtok(cmd_copy, " ", &context); skip_whitespace(&cursor);
char* token = jrpc_strtok(cmd_copy, " ", (char**)&cursor);
if (token == NULL) { if (token == NULL) {
jrpc_debug("Invalid command\n"); jrpc_debug("Invalid command\n");
goto __exit; goto __exit;
@ -775,18 +814,52 @@ char* JRPC_cmd(JRPC* jrpc, const char* cmd) {
goto __exit; goto __exit;
} }
while ((token = jrpc_strtok(NULL, " ", &context)) != NULL) { skip_whitespace(&cursor);
int param_value = atoi(token);
params_array[param_count] = cJSON_CreateNumber(param_value); while (cursor && *cursor != '\0') {
if (!params_array[param_count]) { cJSON* param = NULL;
jrpc_debug("Failed to create JSON number\n"); if (*cursor == '"') {
char* str_param = extract_quoted_string(&cursor);
if (!str_param) {
jrpc_debug("Failed to extract quoted string\n");
goto __exit; goto __exit;
} }
param = cJSON_CreateString(str_param);
free(str_param);
} else {
const char* start = cursor;
while (*cursor != ' ' && *cursor != '\0') {
cursor++;
}
size_t len = cursor - start;
char* token_param = (char*)malloc(len + 1);
if (!token_param) {
jrpc_debug("Failed to allocate memory for token_param\n");
goto __exit;
}
strncpy(token_param, start, len);
token_param[len] = '\0';
param = cJSON_Parse(token_param);
if (!param) {
param = cJSON_CreateString(token_param);
}
free(token_param);
}
if (!param) {
jrpc_debug("Failed to create JSON parameter\n");
goto __exit;
}
params_array[param_count] = param;
param_count++; param_count++;
skip_whitespace(&cursor);
} }
result = // Ensure params_array and param_count are handled correctly when
JRPC_send_request_blocking(jrpc, method, params_array, param_count); // param_count is 0
result = JRPC_send_request_blocking(
jrpc, method, param_count > 0 ? params_array : NULL, param_count);
if (result == NULL) { if (result == NULL) {
jrpc_debug("No result\n"); jrpc_debug("No result\n");
goto __exit; goto __exit;

View File

@ -27,7 +27,7 @@ extern "C" {
#define PARAM_COUNT_NO_CHECK -1 #define PARAM_COUNT_NO_CHECK -1
// Timeout definitions // Timeout definitions
#define ACK_TIMEOUT 50 #define ACK_TIMEOUT 200
#define BLOCKING_TIMEOUT 1000 #define BLOCKING_TIMEOUT 1000
#define RETRY_COUNT 5 #define RETRY_COUNT 5

View File

@ -28,10 +28,11 @@
// "--gtest_filter=time*" // "--gtest_filter=time*"
// "--gtest_filter=flashdb.tsdb1" // "--gtest_filter=flashdb.tsdb1"
// "--gtest_filter=flashdb.base" // "--gtest_filter=flashdb.base"
"--gtest_filter=jrpc.server" // "--gtest_filter=jrpc.server"
// "--gtest_filter=jrpc.client" // "--gtest_filter=jrpc.client"
// "--gtest_filter=jrpc.BlockingRequestBetweenTwoJRPC" // "--gtest_filter=jrpc.BlockingRequestBetweenTwoJRPC"
// "--gtest_filter=jrpc.cmd" // "--gtest_filter=jrpc.cmd"
"--gtest_filter=jrpc.exec_get_val"
], ],
"stopAtEntry": false, "stopAtEntry": false,
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",

View File

@ -261,7 +261,8 @@ void JRPC_server_handle_string(JRPC* self, char* json_str) {
jrpc_free(ack_str); jrpc_free(ack_str);
} }
cJSON** param_array = (cJSON**)jrpc_malloc(param_count * sizeof(cJSON*)); cJSON** param_array =
(cJSON**)jrpc_malloc(param_count * sizeof(cJSON*) + 1);
if (param_array == NULL) { if (param_array == NULL) {
jrpc_debug("Memory allocation failed for param_array\n"); jrpc_debug("Memory allocation failed for param_array\n");
JRPC_send_acknowledgement(self, id->valueint, ACK_MEMORY_ERROR, JRPC_send_acknowledgement(self, id->valueint, ACK_MEMORY_ERROR,
@ -726,17 +727,23 @@ int jrpc_test_server() {
char* jrpc_strtok(char* str, const char* delimiters, char** context) { char* jrpc_strtok(char* str, const char* delimiters, char** context) {
char* start = str ? str : *context; char* start = str ? str : *context;
if (!start) if (!start) {
return NULL; return NULL;
}
while (*start && strchr(delimiters, *start)) // Skip initial delimiters
while (*start && strchr(delimiters, *start)) {
++start; ++start;
if (!*start) }
if (!*start) {
*context = NULL;
return NULL; return NULL;
}
char* end = start; char* end = start;
while (*end && !strchr(delimiters, *end)) while (*end && !strchr(delimiters, *end)) {
++end; ++end;
}
if (*end) { if (*end) {
*end = '\0'; *end = '\0';
@ -748,6 +755,36 @@ char* jrpc_strtok(char* str, const char* delimiters, char** context) {
return start; return start;
} }
static char* extract_quoted_string(const char** input) {
const char* start = *input;
if (*start != '"') {
return NULL;
}
start++;
const char* end = strchr(start, '"');
if (!end) {
return NULL;
}
size_t len = end - start;
char* result = (char*)malloc(len + 1);
if (!result) {
return NULL;
}
strncpy(result, start, len);
result[len] = '\0';
*input = end + 1;
return result;
}
static void skip_whitespace(const char** input) {
if (input == NULL || *input == NULL) {
return;
}
while (**input == ' ' || **input == '\t' || **input == '\n') {
(*input)++;
}
}
char* JRPC_cmd(JRPC* jrpc, const char* cmd) { char* JRPC_cmd(JRPC* jrpc, const char* cmd) {
char* cmd_copy = NULL; char* cmd_copy = NULL;
char* method = NULL; char* method = NULL;
@ -762,8 +799,10 @@ char* JRPC_cmd(JRPC* jrpc, const char* cmd) {
goto __exit; goto __exit;
} }
char* context = NULL; const char* cursor = cmd_copy;
char* token = jrpc_strtok(cmd_copy, " ", &context); skip_whitespace(&cursor);
char* token = jrpc_strtok(cmd_copy, " ", (char**)&cursor);
if (token == NULL) { if (token == NULL) {
jrpc_debug("Invalid command\n"); jrpc_debug("Invalid command\n");
goto __exit; goto __exit;
@ -775,18 +814,52 @@ char* JRPC_cmd(JRPC* jrpc, const char* cmd) {
goto __exit; goto __exit;
} }
while ((token = jrpc_strtok(NULL, " ", &context)) != NULL) { skip_whitespace(&cursor);
int param_value = atoi(token);
params_array[param_count] = cJSON_CreateNumber(param_value); while (cursor && *cursor != '\0') {
if (!params_array[param_count]) { cJSON* param = NULL;
jrpc_debug("Failed to create JSON number\n"); if (*cursor == '"') {
char* str_param = extract_quoted_string(&cursor);
if (!str_param) {
jrpc_debug("Failed to extract quoted string\n");
goto __exit; goto __exit;
} }
param = cJSON_CreateString(str_param);
free(str_param);
} else {
const char* start = cursor;
while (*cursor != ' ' && *cursor != '\0') {
cursor++;
}
size_t len = cursor - start;
char* token_param = (char*)malloc(len + 1);
if (!token_param) {
jrpc_debug("Failed to allocate memory for token_param\n");
goto __exit;
}
strncpy(token_param, start, len);
token_param[len] = '\0';
param = cJSON_Parse(token_param);
if (!param) {
param = cJSON_CreateString(token_param);
}
free(token_param);
}
if (!param) {
jrpc_debug("Failed to create JSON parameter\n");
goto __exit;
}
params_array[param_count] = param;
param_count++; param_count++;
skip_whitespace(&cursor);
} }
result = // Ensure params_array and param_count are handled correctly when
JRPC_send_request_blocking(jrpc, method, params_array, param_count); // param_count is 0
result = JRPC_send_request_blocking(
jrpc, method, param_count > 0 ? params_array : NULL, param_count);
if (result == NULL) { if (result == NULL) {
jrpc_debug("No result\n"); jrpc_debug("No result\n");
goto __exit; goto __exit;

View File

@ -27,7 +27,7 @@ extern "C" {
#define PARAM_COUNT_NO_CHECK -1 #define PARAM_COUNT_NO_CHECK -1
// Timeout definitions // Timeout definitions
#define ACK_TIMEOUT 50 #define ACK_TIMEOUT 200
#define BLOCKING_TIMEOUT 1000 #define BLOCKING_TIMEOUT 1000
#define RETRY_COUNT 5 #define RETRY_COUNT 5

View File

@ -940,7 +940,8 @@ static unsigned long mock_tick_ms(void) {
return pika_platform_get_tick(); return pika_platform_get_tick();
} }
rpc_mapping gtest_rpc_map[] = {{"add", rpc_mapping gtest_rpc_map[] = {
{"add",
[](cJSON* params[], int param_count) -> cJSON* { [](cJSON* params[], int param_count) -> cJSON* {
int a = params[0]->valueint; int a = params[0]->valueint;
int b = params[1]->valueint; int b = params[1]->valueint;
@ -952,6 +953,28 @@ rpc_mapping gtest_rpc_map[] = {{"add",
return cJSON_CreateNumber(2478); return cJSON_CreateNumber(2478);
}, },
0}, 0},
{"concat",
[](cJSON* params[], int param_count) -> cJSON* {
const char* str1 = params[0]->valuestring;
const char* str2 = params[1]->valuestring;
size_t len = strlen(str1) + strlen(str2) + 1;
char* result_str = (char*)malloc(len);
if (!result_str)
return NULL;
strcpy(result_str, str1);
strcat(result_str, str2);
cJSON* result = cJSON_CreateString(result_str);
free(result_str);
return result;
},
2},
{"multiply",
[](cJSON* params[], int param_count) -> cJSON* {
double a = params[0]->valuedouble;
double b = params[1]->valuedouble;
return cJSON_CreateNumber(a * b);
},
2},
RPC_MAP_END}; RPC_MAP_END};
rpc_mapping_nonblocking gtest_nonblocking_rpc_map[] = {RPC_MAP_END}; rpc_mapping_nonblocking gtest_nonblocking_rpc_map[] = {RPC_MAP_END};
@ -1313,4 +1336,39 @@ TEST(jrpc, exec_par_num_err) {
EXPECT_STREQ(response, NULL); EXPECT_STREQ(response, NULL);
} }
TEST(jrpc, exec_concat) {
char* response = execute_cmd("concat hello world");
EXPECT_STREQ(response, "\"helloworld\"");
free(response);
}
TEST(jrpc, exec_multiply) {
char* response = execute_cmd("multiply 3.5 2.0");
EXPECT_STREQ(response, "7");
free(response);
}
TEST(jrpc, exec_multiply_integer) {
char* response = execute_cmd("multiply 3 2");
EXPECT_STREQ(response, "6");
free(response);
}
TEST(jrpc, exec_concat_num_err) {
char* response = execute_cmd("concat hello");
EXPECT_EQ(response, nullptr);
}
TEST(jrpc, exec_concat_str) {
char* response = execute_cmd("concat \"hello\" \"world\"");
EXPECT_STREQ(response, "\"helloworld\"");
free(response);
}
TEST(jrpc, exec_concat_str_space) {
char* response = execute_cmd("concat \"he llo\" \"world\"");
EXPECT_STREQ(response, "\"he lloworld\"");
free(response);
}
TEST_END TEST_END

View File

@ -2,4 +2,4 @@
#define PIKA_VERSION_MINOR 13 #define PIKA_VERSION_MINOR 13
#define PIKA_VERSION_MICRO 3 #define PIKA_VERSION_MICRO 3
#define PIKA_EDIT_TIME "2024/07/10 20:34:31" #define PIKA_EDIT_TIME "2024/07/15 17:00:25"