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 all 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
209 changes: 209 additions & 0 deletions native/goIntSlice.c
@@ -0,0 +1,209 @@
#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';
}

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

long decode_u64_array( const GoString* src, long* p, GoIntSlice* arr){
const char* pos = src->buf;
int i =*p;
int len = src->len;
//check space
while(i<len && is_space(pos[i])){
i++;
}
//check left bracket and eof
if(i >= len || pos[i] != '['){
*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
uint64_t num = 0;
while(i < len){
//Jump back if it's a space
while(i < len && is_space(pos[i])){
i++;
}
//eof or the first one is not a number, it must be illegal
if(i >= len || pos[i]<'0' || pos[i]>'9'){
//"[ ]" is true example
if(pos[i]==']' && k==0){
arr->len = k;
*p = i + 1;
return 0;
}
*p = i;
arr->len = 0;
return ERR_INVAL;
}else{
num = char_to_num(pos[i]);
}
i++;
//"0123"is false
if(i>=len || (num == 0 && is_integer(pos[i]))){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
//parse the digital and judge the overflow
while(i < len && is_integer(pos[i])){
if( __builtin_mul_overflow(num,10,&num) || __builtin_add_overflow(num,char_to_num(pos[i]),&num)){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
i++;
}
while(i < len && pos[i] != ',' && pos[i] != ']'){
if(isspace(pos[i])){
i++;
}else{
*p = i;
arr->len = 0;
return ERR_INVAL;
}
}
//If the capacity is insufficient, return ERR_ RECURSE_ MAX
if(k >= arr->cap){
*p = i;
return ERR_RECURSE_MAX;
}
(arr->uptr)[k++] = num;
if (pos[i] == ']') {
arr->len = k;
*p = i + 1;
return 0;
}else{
i++;
}
}
*p = i;
arr->len = 0;
return ERR_INVAL;
}

long decode_i64_array(const GoString* src, long* p, GoIntSlice* arr){
const char* pos = src->buf;
int i =0;
int len = src->len;
while(i < len && is_space(pos[i])){
i++;
}
if(i >= len || pos[i] != '['){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
i++;
int k =0;
int64_t num = 0;
//Define a flag to represent the symbol of a signed number
char flag ='+';
while(i < len){
while(i < len && is_space(pos[i])){
i++;
}
if(i >= len || (pos[i]<'0' || pos[i]>'9') && (pos[i]!='-' )){
if(pos[i]==']' && k==0){
arr->len = k;
*p = i + 1;
return 0;
}
*p = i;
arr->len = 0;
//The first one is neither a number nor a Plus or minus sign, so it must be illegal
return ERR_INVAL;
}else if( pos[i]=='-'){
//Determine symbols , and the first digit immediately after it is also stored in num and i+1
flag = pos[i];
i++;
if(i>=len || !is_integer(pos[i])){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
num = char_to_num(pos[i]);
}else{
num = char_to_num(pos[i]);
}
i++;
if(i>=len || (num == 0 && is_integer(pos[i]))){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
while(i < len && is_integer(pos[i])){
if( __builtin_mul_overflow(num,10,&num) || __builtin_add_overflow(num,char_to_num(pos[i]),&num)){
*p = i;
arr->len = 0;
return ERR_INVAL;
}
i++;
}
while(i < len && pos[i] != ',' && pos[i] != ']'){
if(isspace(pos[i])){
i++;
}else{
*p = i;
arr->len = 0;
return ERR_INVAL;
}
}
//If the capacity is insufficient, return ERR_ RECURSE_ MAX
if(k >= arr->cap){
*p = i;
return ERR_RECURSE_MAX;
}
if(flag =='-'){
num = -(num);
}
(arr->iptr)[k++] = num;
if (pos[i] == ']') {
arr->len = k;
*p = i + 1;
return 0;
}else{
i++;
}
flag = '+'; //Reset flag to positive sign
}
*p = i;
arr->len = 0;
return ERR_INVAL;
}
3 changes: 2 additions & 1 deletion native/native.c
Expand Up @@ -24,4 +24,5 @@
#include "atof_native.c"
#include "scanning.c"
#include "f32toa.c"
#include "to_lower.c"
#include "goIntSlice.c"
#include "to_lower.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[12][100] = {"[1,2,18446744073709551615]","[-789,3, 6,45]","[ ],","[1,023,4,4]","[1,24 5,3,4]","[ 1,2,3,4]","[- 789,3, 6,45]","[1,2,3]","[1 ,2,3,4]","[1,-2,-3,4]","[1,-2, -3, 4]","[1, -2.3, 4]"};
for(int i=0;i<12;i++){
test_decode_u64_array(teststr[i]);
printf("*");
test_decode_i64_array(teststr[i]);
printf("*");
}
}