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 15 commits
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
279 changes: 279 additions & 0 deletions native/goIntSlice.c
@@ -0,0 +1,279 @@
#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>

#include "native.h"
#include "types.h"

#define ERR_INVAL 2
#define ERR_RECURSE_MAX 7

typedef struct {
union { // the pointer of u64 or i64 array
int64_t* iptr;
uint64_t* uptr;
};
size_t len; // the length of slice
size_t cap; // the capacity of slice
} GoIntSlice;

bool is_space(char a){
if( a == ' '||a == '\t'||a == '\r'||a == '\n'){
return true;
}else{
return false;
}
}

bool is_integer(char a){
return a>='0'&& a<='9';
}

bool is_overflow(int i ,size_t srclen){
return i >= srclen;
}

int char_to_num(char c){
return c-'0';
}

long decode_u64_array( const GoString* src, long* p, GoIntSlice* arr){
char* pos = src->buf;
int i =*p;
//If there is a space before the beginning, eat the space first
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
while(is_space(pos[i])){
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
i++;
}
if(is_overflow(i,src->len)){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
//If the first one is not a left bracket, returning it directly is illegal
if(pos[i] != '['){
//P points to the first position after the error
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
*p = i;
arr->len = 0;
return ERR_INVAL;
}
//when program runs here, it's a left parenthesis
i++;
//K+1 represents the number of digits in the string src
int k =0;
//Num is used to store the current number
int num = 0;
while(pos[i] !='\0'){
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
//If the capacity is insufficient, return ERR_ RECURSE_ MAX
if(k==arr->cap){
*p = i+1;
return ERR_RECURSE_MAX;
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
}
//Jump back if it's a space
while(is_space(pos[i])){
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
i++;
}
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
if(is_overflow(i,src->len)){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
//The first one is not a number, it must be illegal
if(pos[i]<'0' || pos[i]>'9'){
*p = i;
arr->len = 0;
return ERR_INVAL;
}else{
num = char_to_num(pos[i]);
}
i++;
while(!is_space(pos[i])&& pos[i] !=','){
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
if(is_overflow(i,src->len)){
*p = i;
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
arr->len = 0;
return ERR_INVAL;
}
//If it is not followed by a space or a comma, it indicates that it is a number or an error has occurred
if(is_integer(pos[i])){
num = num*10 + char_to_num(pos[i]);
i++;
//check if there are some illegal symbol after the right bracket ,if not, it can be closed and a value can be returned
}else if(pos[i] ==']'){
while(!is_overflow(i+1,src->len)){
if(is_space(pos[i+1])){
i++;
}else{
*p = i+1;
arr->len = 0;
return ERR_INVAL;
}
}
(arr->uptr)[k] = num;
arr->len = k+1;
*p = src->len;
return 0;
}else{
//If it's not a number or a comma, it's an error. Point to the position after the error and return ERR_ INVAL
*p = i;
arr->len = 0;
return ERR_INVAL;
}
}
while(is_space(pos[i])){
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
i++;
}
if(pos[i] ==']'){
while(!is_overflow(i+1,src->len)){
if(is_space(pos[i+1])){
i++;
}else{
*p = i+1;
arr->len = 0;
return ERR_INVAL;
}
}
(arr->uptr)[k] = num;
arr->len = k+1;
*p = src->len;
return 0;
}
if(is_integer(pos[i])){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
if(pos[i] ==','){ //If it's a comma, put it away
(arr->uptr)[k] = num;
k++;
i++;
}
if(is_overflow(i,src->len)){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
}
}

long decode_i64_array(const GoString* src, long* p, GoIntSlice* arr){
char* pos = src->buf;
int i =0;

while(is_space(pos[i])){
i++;
}
if(is_overflow(i,src->len)){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
if(pos[i] != '['){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
i++;
int k =0;
int num = 0;
//Define a flag to represent the symbol of a signed number
char flag ='+';
while(pos[i] !=0){
if(k==arr->cap){
*p = i+1;
return ERR_RECURSE_MAX;
}
while(is_space(pos[i])){
i++;
}
if(is_overflow(i,src->len)){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
if((pos[i]<'0' || pos[i]>'9') && (pos[i]!='+' && pos[i]!='-' )){
*p = i;
arr->len = 0;
//The first one is neither a number nor a Plus¨Cminus sign, so it must be illegal
liuq19 marked this conversation as resolved.
Show resolved Hide resolved
return ERR_INVAL;
}else if(pos[i]=='+' || pos[i]=='-'){
//If it is a symbol, then the symbol is fixed, and the first digit immediately after it is also stored in num and i+1
flag = pos[i];
i++;
num = char_to_num(pos[i]);
}else{
num = char_to_num(pos[i]);
}
i++;
while(!is_space(pos[i])&& pos[i] !=','){
if(is_overflow(i,src->len)){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
if(is_integer(pos[i])){
num = num*10 + char_to_num(pos[i]);
i++;
}else if(pos[i] ==']'){
while(!is_overflow(i+1,src->len)){
if(is_space(pos[i+1])){
i++;
}else{
*p = i+1;
arr->len = 0;
return ERR_INVAL;
}
}
if(flag =='-'){
num = -(num);
}
(arr->iptr)[k] = num;
arr->len = k+1;
*p = src->len;
return 0;
}else{
*p = i;
arr->len = 0;
return ERR_INVAL;
}
}
while(is_space(pos[i])){
i++;
}
if(pos[i] ==']'){
while(!is_overflow(i+1,src->len)){
if(is_space(pos[i+1])){
i++;
}else{
*p = i+1;
arr->len = 0;
return ERR_INVAL;
}
}
(arr->uptr)[k] = num;
arr->len = k+1;
*p = src->len;
return 0;
}
if(is_integer(pos[i])){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
if(pos[i] ==','){
if(flag =='-'){
num = -(num);
}
(arr->iptr)[k] = num;
k++;
i++;
}
if(is_overflow(i,src->len)){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
flag = '+'; //Reset flag to positive sign
}
}
4 changes: 3 additions & 1 deletion native/native.c
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"

64 changes: 64 additions & 0 deletions native/unittest/unittest_goIntSlice.c
@@ -0,0 +1,64 @@
#include <stdio.h>
#include <string.h>

#include "../goIntSlice.c"

void test_decode_i64_array(const char* test_str){
GoIntSlice demo;
size_t cap = 4096;
demo.iptr = (int64_t*)malloc(cap * sizeof(int64_t));
demo.len = 0;
demo.cap = cap;

long p = 0;
long* pp = &p;
GoString test;

const char* str = test_str;
test.buf = str;
test.len = strlen(str);

long res = decode_i64_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.iptr);
}

void test_decode_u64_array(const char* test_str){
GoIntSlice demo;
size_t cap = 4096;
demo.uptr = (uint64_t*)malloc(cap * sizeof(uint64_t));
demo.len = 0;
demo.cap = cap;

long p = 0;
long* pp = &p;
GoString test;

const char* str = test_str;
test.buf = str;
test.len = strlen(str);

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.uptr[z]);
}
free(demo.uptr);
}

int main(){
char teststr[11][100] = {" ","[1,20,3,4],","[1,2,3.5,4]","[1,20,3,4]","[ 1,2,3,4]","[1,2,3,4]","[1,2,3]","[1 ,2,3,4]","[1,-2,-3,4]","[1,-2, -3, 4]","[1, -2.3, 4]"};
for(int i=0;i<11;i++){
test_decode_u64_array(teststr[i]);
printf("*");
test_decode_i64_array(teststr[i]);
printf("*");
}
}