Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

to decode u64 or i64 slice in native c #455

Draft
wants to merge 25 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
214 changes: 214 additions & 0 deletions native/goIntSlice.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>

#include <native.h>

#define ERR_INVAL 2
#define ERR_RECURSE_MAX 7

typedef struct {
union { // u64 或 i64 array 的指针
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
int64_t* iptr;
uint64_t* uptr;
};
size_t len; // s 长度
size_t cap; // slice 容量
} GoIntSlice;



bool isSpace(char a){
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
if( a == 32){
return true;
}else{
return false;
}
}

bool isIntger(char a){
if(a<48 ||a>57){
return false;
}else{
return true;
}
}

int charToNum(char c){
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
return c-48;
}
// 输入参数:src 是 输入的json, p 是当前位置.
// 返回值:
// 如果是合法的json 数组,返回0 表示解析成功,
// 如果解析的元素是非法json,返回-ERR_INVAL
// 如果解析的元素是json 类型不匹配,但是 json 是合法的,返回 -ERR_MISMATCH
// 如果 slice cap 不够,返回 -ERR_RECURSE_MAX。
// 将解析结果存放到arr中,len +1,直到cap。

// 例子1
// 输入:
// src: 一个字符串,是json整数数组,例如"[1,2,3,4]"
// p: 当前的位置,假如是0,
// arr: 假如是len=0, cap=256
// 输出:
// p: 解析后指向的位置,这里应该是json结束位置,即9
// arr: uptr指针依次存入1,2,3,4. 然后len = 4, cap不变。
// 返回值是0

// 例子2
// 输入:
// src: 一个字符串,例如"{[]}",和 "[1,2,3,4.5], 这个json片段是非法的或者不是数字
// p: 当前的位置,假如是0,
// arr: 假如是len=0, cap=256
// 输出:
// p: 解析后指向的位置,这里应该是json出错位置
// arr: 解析后发现是非法的json,需要返回-ERR_INVALID,同时arr中长度需要重置为0
// 返回值是 ERR_INVAL

long decode_u64_array( const GoString* src, long* p, GoIntSlice* arr){ //无符号数字
char* pos = src->buf;
int i =0;
liuq19 marked this conversation as resolved.
Show resolved Hide resolved

while(isSpace(*(pos+i))){ //如果最开始前面有空格,先吃掉空格
i++;
}
if(*(pos+i) != 91){ //第一个不是左中括号的话直接返回非法
*p = i+1; //p指向第一个出错后位置
arr->len = 0;
return ERR_INVAL;
}
i++; //是左括号
int k =0; //需要一个游标k,m
int num = 0; //存储数字
while(*(pos+i) !=0){
if(k==arr->cap){ //容量不够
*p = i+1;
return ERR_RECURSE_MAX;
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
}
while(isSpace(*(pos+i))){ //是空格就往后跳
i++;
}
if(*(pos+i)<48 || *(pos+i)>57){
*p = i+1; //p指向第一个出错后位置
arr->len = 0;
return ERR_INVAL; //第一个不是数字肯定非法
}else{
num = charToNum(*(pos+i));
}

i++;
while(!isSpace(*(pos+i))&& *(pos+i) !=44){ //后面不是空格也不是逗号, 那么说明是数字或者发生错误
if(isIntger(*(pos+i))){

num = num*10 + charToNum(*(pos+i));
i++;
}else if(*(pos+i) ==93){ //右括号的话可以收起来 ,并返回值
(arr->uptr)[k] = num;
arr->len = k+1;
*p = i+1;
return 0;
}else{
*p = i+1; //不是数字不是逗号就出错了 p指向出错后位置
arr->len = 0;
return ERR_INVAL;
}
}
while(isSpace(*(pos+i))){
i++;
}
if(*(pos+i) ==44){ //是逗号的话收起来
(arr->uptr)[k] = num;
k++;
i++;
}


}




}



long decode_i64_array(const GoString* src, long* p, GoIntSlice* arr){//有符号数字
char* pos = src->buf;
int i =0;

while(isSpace(*(pos+i))){ //如果最开始前面有空格,先吃掉空格
i++;
}
if(*(pos+i) != 91){ //第一个不是左中括号的话直接返回非法
*p = i+1; //p指向第一个出错后位置
arr->len = 0;
return ERR_INVAL;
}
i++; //是左括号
int k =0; //需要一个游标k,m
int num = 0; //存储数字
char flag ='+'; //把flag初始化为正号
while(*(pos+i) !=0){
if(k==arr->cap){ //容量不够
*p = i+1;
return ERR_RECURSE_MAX;
}
while(isSpace(*(pos+i))){ //是空格就往后跳
i++;
}
if((*(pos+i)<48 || *(pos+i)>57) && (*(pos+i)!=43 && *(pos+i)!=45 )){

*p = i+1; //p指向第一个出错后位置
arr->len = 0;
return ERR_INVAL; //第一个既不是数字,又不是正负号,那么肯定非法
}else if(*(pos+i)==43 || *(pos+i)==45){
flag = *(pos+i); //是符号的话就定符号 ,并且后面紧挨着的第一个数字也存入num 并把i+1
i++;
num = charToNum(*(pos+i));

}else{
num = charToNum(*(pos+i));
}

i++;
while(!isSpace(*(pos+i))&& *(pos+i) !=44){ //后面不是空格也不是逗号, 那么说明是数字或者发生错误
if(isIntger(*(pos+i))){

num = num*10 + charToNum(*(pos+i));
i++;
}else if(*(pos+i) ==93){ //右括号的话可以收起来 ,并返回值
if(flag ==45){
num = -(num);
}
(arr->iptr)[k] = num;
arr->len = k+1;
*p = i+1;
return 0;
}else{
*p = i+1; //不是数字不是逗号就出错了 p指向出错后位置
arr->len = 0;
return ERR_INVAL;
}
}
while(isSpace(*(pos+i))){
i++;
}
if(*(pos+i) ==44){ //是逗号的话收起来

if(flag ==45){
num = -(num);
}
(arr->iptr)[k] = num;
k++;
i++;
}
flag = '+'; //重新把flag置为正号

}
}



4 changes: 3 additions & 1 deletion native/native.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@
#include "atof_eisel_lemire.c"
#include "atof_native.c"
#include "scanning.c"
#include "f32toa.c"
#include "f32toa.c"
#include "goIntSlice.c"

52 changes: 52 additions & 0 deletions native/unittest/test_goIntSlice.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "../goIntSlice.c"

#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>



int main(){
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
// 初始化GoIntSlice
GoIntSlice demo;
size_t cap = 4096;
//demo.uptr = (uint64_t*)malloc(cap * sizeof(uint64_t));
demo.iptr = (int64_t*)malloc(cap * sizeof(int64_t));
demo.len = 0;
demo.cap = cap;

// long* pp; // 这种是一个野指针,而且没有初始化,
long p = 0;
long* pp = &p;
GoString test;
/*
目前测试用例满足的有:
"{[1,2,3,4]" 错误用例
"[1,2,3.5,4]" 错误用例
"[1, 2,3, 4]" 正确用例但是有不规则空格
"[ 1,2,3,4]" 正确用例但是有不规则空格
"[1,2,3,4]" 正确用例
"[1,2,3]" 正确用例
"[1 ,2,3,4]" 正确用例但是有不规则空格
*/


const char* str = "[1,-2,3,-4,5]"; // 使用C语言字符串写法更加简洁,而且结尾自动加上了'\0'
test.buf = str;
test.len = strlen(str);


long res = decode_i64_array(&test,pp,&demo);
//long res = decode_u64_array(&test,pp,&demo);

printf("%lld ,%lld\n",*pp,res);
for(int z=0;z<demo.len;z++){
printf("%d ",demo.iptr[z]);
}

// 测试完释放内存
free(demo.uptr);
}