DtsodV24 deserialization almost completed

This commit is contained in:
Timerix22 2022-03-01 22:31:26 +03:00
parent 9f3cb51c2d
commit df39b92cfd
21 changed files with 427 additions and 101 deletions

View File

@ -6,7 +6,9 @@
"functional": "c",
"istream": "c",
"ranges": "c",
"streambuf": "c"
"streambuf": "c",
"chrono": "c",
"string": "c"
},
"C_Cpp.errorSquiggles": "Disabled"
}

View File

@ -1,4 +1,5 @@
SRC=$(wildcard src/*c) $(wildcard src/**/*.c)
TESTS=$(wildcard tests/*c) $(wildcard tests/**/*.c)
OUTDIR=bin/
OUTFILE=$(OUTDIR)dtsodc.com
CMP=gcc
@ -14,10 +15,10 @@ clear_bin:
clang: CMP=clang
clang: all
CMPARGS= -Wall $(SRC) -o $(OUTFILE)
CMPARGS= -Wall $(SRC) $(TESTS) -o $(OUTFILE)
build:
@echo -e '\n\e[96m----------------[build]----------------\e[0m'
$(CMP) -O1 -flto -Wno-discarded-qualifiers $(CMPARGS)
$(CMP) -O1 -flto $(CMPARGS)
build_dbg:
@echo -e '\n\e[96m--------------[build_dbg]--------------\e[0m'
$(CMP) -O0 -g $(CMPARGS).dbg

View File

@ -4,15 +4,20 @@
#define ARR_BC 2
#define ARR_BL 8
Hashtable* __parse(const char* text, bool called_recursively){
Hashtable* __deserialize(char* text, bool calledRecursively){
Hashtable* dict=Hashtable_create();
bool partOfDollarList=false;
char c;
bool partOfDollarList=false;
bool readingList=false;
void throw_wrongchar(char _c){
char errstr[]="unexpected <c>";
errstr[12]=_c;
throw(errstr);
char errBuf[]="unexpected <c> at:\n \""
"00000000000000000000000000000000"
"\"";
errBuf[12]=_c;
for(uint8 i=0;i<32;i++)
errBuf[i+22]=*(text-16+i);
throw(errBuf);
};
void SkipComment(){
@ -30,7 +35,7 @@ Hashtable* __parse(const char* text, bool called_recursively){
SkipComment();
break;
case '}':
if(!called_recursively) throw_wrongchar(c);
if(!calledRecursively) throw_wrongchar(c);
case ':':
return nameStr;
case '$':
@ -41,6 +46,7 @@ Hashtable* __parse(const char* text, bool called_recursively){
case '[': case ']':
case '{':
throw_wrongchar(c);
break;
default:
nameStr.length++;
break;
@ -52,11 +58,13 @@ Hashtable* __parse(const char* text, bool called_recursively){
Unitype ReadValue(){
string valueStr={text,0};
bool endOfList=false;
//returns part of <text> with quotes
string ReadString(){
bool prevIsBackslash = false;
string str={text,1};
while ((c=*++text)!='"' || prevIsBackslash){
printf("%c",c);
if (!c) throw(ERR_ENDOFSTR);
prevIsBackslash= c=='\\' && !prevIsBackslash;
str.length++;
@ -64,19 +72,96 @@ Hashtable* __parse(const char* text, bool called_recursively){
str.length++;
return str;
};
Autoarr2(Unitype)* ReadList(){
throw(ERR_ENDOFSTR);
return NULL;
Autoarr2(Unitype)* list=malloc(sizeof(Autoarr2(Unitype)));
*list=Autoarr2_create(Unitype,ARR_BC,ARR_BL);
readingList=true;
while (true){
Autoarr2_add(list,ReadValue());
if (!readingList) break;
}
return list;
};
Hashtable* ReadDtsod(){
if(*++text) //skips {
return __deserialize(text,true);
else {
throw(ERR_ENDOFSTR);
return NULL;
}
};
Unitype ParseValue(string str){
throw(ERR_ENDOFSTR);
Unitype ParseValue(string str){
const string nullStr={"null",4};
const string trueStr={"true",4};
const string falseStr={"false",5};
switch(*str.ptr){
case 'n':
if(string_compare(str,nullStr))
return UniNull;
else throw_wrongchar(*str.ptr);
break;
case 't':
if(string_compare(str,trueStr))
return UniTrue;
else throw_wrongchar(*str.ptr);
break;
case 'f':
if(string_compare(str,falseStr))
return UniFalse;
else throw_wrongchar(*str.ptr);
break;
case '"':
if(str.ptr[str.length-1]=='"'){
//removing quotes
string _str={str.ptr+1,str.length-1};
return UniPtr(CharPtr, string_cpToCharPtr(_str));
}
else throw_wrongchar(*str.ptr);
break;
default:
switch(str.ptr[str.length-1]){
case 's':
return value_str[value_str.Length - 2] == 'u'
? value_str.Remove(value_str.Length - 2).ToUShort()
: value_str.Remove(value_str.Length - 1).ToShort();
case 'u':
return value_str.Remove(value_str.Length - 1).ToUInt();
case 'i':
return value_str[value_str.Length - 2] == 'u'
? value_str.Remove(value_str.Length - 2).ToUInt()
: value_str.Remove(value_str.Length - 1).ToInt();
case 'l':
return value_str[value_str.Length - 2] == 'u'
? value_str.Remove(value_str.Length - 2).ToULong()
: value_str.Remove(value_str.Length - 1).ToLong();
case 'b':
return value_str[value_str.Length - 2] == 's'
? value_str.Remove(value_str.Length - 2).ToSByte()
: value_str.Remove(value_str.Length - 1).ToByte();
case 'f':
return value_str.Remove(value_str.Length - 1).ToFloat();
case 'e':
return value_str[value_str.Length - 2] == 'd'
? value_str.Remove(value_str.Length - 2).ToDecimal()
: throw new Exception("can't parse value:" + value_str);
default:
/* if (value_str.Contains('.'))
return (object)(value_str.ToDouble());
else
{
try { return (object)(value_str.ToInt()); }
catch (FormatException)
{
Log("r", $"can't parse value: {value_str}");
return null;
}
} */
}
}
throw(ERR_NOTIMPLEMENTED);
return UniNull;
};
@ -103,13 +188,14 @@ Hashtable* __parse(const char* text, bool called_recursively){
case '[':
return UniPtr(AutoarrUnitypePtr,ReadList());
case ']':
endOfList=true;
readingList=false;
break;
case '{':
return UniPtr(HashtablePtr,ReadDtsod());
case '=': case ':':
case '}': case '$':
throw_wrongchar(c);
break;
default:
valueStr.length++;
break;
@ -119,12 +205,11 @@ Hashtable* __parse(const char* text, bool called_recursively){
return UniNull;
};
text--;
while((c=*++text)){
while((c=*text++)){
string name=ReadName();
if(name.length==0) //closing figure bracket in recursive call or end of file
if(name.length==0) //end of file or '}' in recursive call
return dict;
char* nameCPtr=string_toCharPtr(name);
char* nameCPtr=string_cpToCharPtr(name);
Unitype value=ReadValue();
if(partOfDollarList){
Autoarr2(Unitype)* list;
@ -143,4 +228,4 @@ Hashtable* __parse(const char* text, bool called_recursively){
return dict;
}
Hashtable* DtsodV24_parse(const char* text) { return __parse(text,false); }
Hashtable* DtsodV24_deserialize(char* text) { return __deserialize(text,false); }

View File

@ -0,0 +1,187 @@
#include "DtsodV24.h"
#include "../Autoarr/StringBuilder.h"
#define ARR_BC 2
#define ARR_BL 8
Hashtable* __parse(string textStr, bool called_recursively){
Hashtable* dict=Hashtable_create();
char* text=textStr.ptr;
char c;
bool partOfDollarList=false;
bool readingList=false;
void throw_wrongchar(char _c){
char errstr[]="unexpected <c>";
errstr[12]=_c;
throw(errstr);
};
void SkipComment(){
while((c=*++text)!='\n')
if(!c) throw(ERR_ENDOFSTR);
};
string ReadName(){
string nameStr={text,0};
while ((c=*++text)) switch (c){
case ' ': case '\t':
case '\r': case '\n':
break;
case '#':
SkipComment();
break;
case '}':
if(!called_recursively) throw_wrongchar(c);
case ':':
return nameStr;
case '$':
partOfDollarList=true;
break;
case '=': case ';':
case '\'': case '"':
case '[': case ']':
case '{':
throw_wrongchar(c);
default:
nameStr.length++;
break;
}
if(nameStr.length>0) throw(ERR_ENDOFSTR);
return nameStr;
};
Unitype ReadValue(){
string valueStr={text,0};
//returns part of <text> with brackets
string ReadString(){
bool prevIsBackslash = false;
string str={text,1};
while ((c=*++text)!='"' || prevIsBackslash){
if (!c) throw(ERR_ENDOFSTR);
prevIsBackslash= c=='\\' && !prevIsBackslash;
str.length++;
}
str.length++;
return str;
};
Autoarr2(Unitype)* ReadList(){
Autoarr2(Unitype)* list=malloc(sizeof(Autoarr2(Unitype)));
*list=Autoarr2_create(Unitype,ARR_BC,ARR_BL);
readingList=true;
while (true){
Autoarr2_add(list,ReadValue());
if (!readingList) break;
}
return list;
};
Hashtable* ReadDtsod(){
short bracketBalance = 1;
string dtsodStr={text+1,0};
while ((c=*++text))//пропускает начальный символ '{'
{
if(bracketBalance) switch (c)
{
case ' ': case '\t':
case '\r': case '\n':
break;
case '#':
SkipComment();
break;
case '{':
bracketBalance++;
dtsodStr.length++;
break;
case '}':
bracketBalance--;
if (bracketBalance != 0)
dtsodStr.length++;
break;
case '"':
string _str=ReadString();
dtsodStr.length+=_str.length;
break;
default:
dtsodStr.length++;
break;
}
else return __parse(dtsodStr,true);
}
throw(ERR_ENDOFSTR);
return NULL;
};
Unitype ParseValue(string str){
throw(ERR_NOTIMPLEMENTED);
return UniNull;
};
while ((c=*++text)) switch (c){
case ' ': case '\t':
case '\r': case '\n':
break;
case '#':
SkipComment();
break;
case '"':
valueStr=ReadString();
break;
case '\'':
text++;
char valueChar=*++text;
if (*++text != '\'') throw("after <'> should be char");
else if (valueStr.length!=0) throw("char assignement error");
else return Uni(Char,valueChar);
break;
case ';':
case ',':
return ParseValue(valueStr);
case '[':
return UniPtr(AutoarrUnitypePtr,ReadList());
case ']':
readingList=false;
break;
case '{':
return UniPtr(HashtablePtr,ReadDtsod());
case '=': case ':':
case '}': case '$':
throw_wrongchar(c);
default:
valueStr.length++;
break;
}
throw(ERR_ENDOFSTR);
return UniNull;
};
while((c=*text++)){
string name=ReadName();
if(name.length==0) //closing figure bracket in recursive call or end of file
return dict;
char* nameCPtr=string_cpToCharPtr(name);
Unitype value=ReadValue();
if(partOfDollarList){
Autoarr2(Unitype)* list;
Unitype lu;
if(Hashtable_try_get(dict,nameCPtr, &lu))
list=(Autoarr2(Unitype)*)lu.VoidPtr;
else{
list=malloc(sizeof(Autoarr2(Unitype)));
*list=Autoarr2_create(Unitype,ARR_BC,ARR_BL);
Hashtable_add(dict,nameCPtr,UniPtr(AutoarrUnitypePtr,list));
}
Autoarr2_add(list,value);
}
else Hashtable_add(dict,nameCPtr,value);
}
return dict;
}
Hashtable* DtsodV24_parse(const char* text) { return __parse((text,false); }

View File

@ -2,4 +2,5 @@
#include "../base/base.h"
#include "../Hashtable/Hashtable.h"
Hashtable* DtsodV24_parse(const char* text);
Hashtable* DtsodV24_deserialize(char* text);
string DtsodV24_serialize(Hashtable* dtsod);

View File

@ -53,7 +53,6 @@ void Hashtable_expand(Hashtable* ht){
ht->rows=newrows;
}
#include "../tests/tests.h"
Autoarr2(KeyValuePair)* getrow(Hashtable* ht, char* key, bool can_expand){
Autoarr2(KeyValuePair)* ar=ht->rows+ihash(key)%HT_HEIGHTS[ht->hein];
if(can_expand && Autoarr2_length(ar)==Autoarr2_max_length(ar))
@ -76,7 +75,7 @@ Unitype* Hashtable_getptr(Hashtable* ht, char* key){
uint32 arlen=Autoarr2_length(ar);
for(uint32 i=0;i<arlen;i++){
KeyValuePair* p=Autoarr2_getptr(ar,i);
if(mystrcmp(key,p->key)) return &p->value;
if(charbuf_compare(key,p->key)) return &p->value;
}
return NULL;
}
@ -86,7 +85,7 @@ Unitype Hashtable_get(Hashtable* ht, char* key){
uint32 arlen=Autoarr2_length(ar);
for(uint32 i=0;i<arlen;i++){
KeyValuePair p=Autoarr2_get(ar,i);
if(mystrcmp(key,p.key)) return p.value;
if(charbuf_compare(key,p.key)) return p.value;
}
return UniNull;
}

View File

@ -26,7 +26,7 @@ void Hashtable_free(Hashtable* ht);
uint32 Hashtable_height(Hashtable* ht);
//adds charptr and value to new KeyValuePair
//use mystrcpy() to create new string if needed
//use charbuf_copy() to create new string if needed
#define cpair(key,value) (KeyValuePair){key,value}

View File

@ -7,7 +7,7 @@ typedef struct SearchTreeNode{
Unitype value;
} STNode;
STNode* STNode_create(void);
STNode* STNode_create();
void STNode_free(STNode* node);
void ST_push(STNode* node, const char* key, Unitype value);

View File

@ -7,3 +7,13 @@
// sleep function based on std nanosleep()
void fsleep(float sec);
// executes codeblock and prints execution time
#define optime(opname,repeats,codeblock) ({\
clock_t start=clock();\
for(uint64 ___OPREP=0;___OPREP<repeats;___OPREP++)\
(codeblock);\
clock_t stop=clock();\
double t=(double)(stop-start)/CLOCKS_PER_SEC/repeats;\
printf("\e[93moperation \e[94m%s\e[93m took \e[94m%lf \e[93mseconds\n",opname,t);\
})

View File

@ -8,7 +8,7 @@ uint32 mystrlen(char* str){
}
//allocates new char[] and copies src there
char* mystrcpy(char* src){
char* charbuf_copy(char* src){
uint32 len=mystrlen(src);
char* dst=malloc(len*sizeof(char));
while(len-->0)
@ -16,42 +16,53 @@ char* mystrcpy(char* src){
return dst;
}
//compares two strings, NullPtr-friendly
bool mystrcmp(char* key0, char* key1){
if(!key0) return key1 ? 0 : 1;
else if(!key1) return 0;
while(*key0&&*key1){
if(*key0!=*key1) return 0;
key0++;
key1++;
}
return 1;
//compares two char buffers, NullPtr-friendly
bool charbuf_compare(char* key0, char* key1){
if(!key0) return key1 ? false : true;
if(!key1) return false;
while(*key0&&*key1)
if(*key0++ != *key1++)
return false;
return true;
}
//multiplies char n times
char* mystrmtpl(char c, uint32 n){
char* char_multiply(char c, uint32 n){
char* rez=malloc(n+1);
rez[n]=0;
while(n>0)
rez[--n]=c;
while(n-->0)
rez[n]=c;
return rez;
}
char* string_toCharPtr(string str){
//copies str content to new char pointer value (adding '\0' at the end)
char* string_cpToCharPtr(string str){
char* cptr=malloc(str.length*sizeof(char)+1);
if(str.length==0) return NULL;
cptr[str.length]=0;
while(str.length>0)
cptr[--str.length]=str.ptr[str.length];
while(str.length-->0)
cptr[str.length]=str.ptr[str.length];
return cptr;
}
string string_fromCharPtr(char* cptr){
//copies cptr content (excluding '\0' at the end) to new string
string string_cpFromCharPtr(char* cptr){
if(!cptr) return stringNull;
string str;
str.length=mystrlen(cptr);
str.length=mystrlen(cptr)-1;
str.ptr=malloc(str.length);
for(uint32 i=0;i>str.length;i++)
for(uint32 i=0;i<str.length;i++)
str.ptr[i]=cptr[i];
return str;
}
//compares two strings, NullPtr-friendly
bool string_compare(string str0, string str1){
if(str0.length!=str1.length) return false;
if(!str0.ptr) return str1.ptr ? false : true;
else if(!str1.ptr) return false;
while(str0.length-->0)
if(*str0.ptr++ != *str1.ptr++)
return false;
return true;
}

View File

@ -6,13 +6,13 @@
uint32 mystrlen(char* str);
//allocates new char[] and copies src there
char* mystrcpy(char* src);
char* charbuf_copy(char* src);
//compares two strings, NullPtr-friendly
bool mystrcmp(char* key0, char* key1);
//compares two char buffers, NullPtr-friendly
bool charbuf_compare(char* key0, char* key1);
//multiplies char n times
char* mystrmtpl(char c, uint32 n);
char* char_multiply(char c, uint32 n);
//my fixed length string struct
//doesn't store '\0' at the end
@ -24,7 +24,10 @@ typedef struct string{
static const string stringNull={NULL,0};
//copies str content to new char pointer value (adding '\0' at the end)
char* string_toCharPtr(string str);
char* string_cpToCharPtr(string str);
//copies cptr content (excluding '\0' at the end) to new string
string string_fromCharPtr(char* cptr);
string string_cpFromCharPtr(char* cptr);
//compares two strings, NullPtr-friendly
bool string_compare(string str0, string str1);

View File

@ -14,7 +14,7 @@ typedef enum my_type{
Null, Float, Double, Char, Bool,
UInt8, Int8, UInt16, Int16, UInt32, Int32, UInt64, Int64,
UInt8Ptr, Int8Ptr, UInt16Ptr, Int16Ptr, UInt32Ptr, Int32Ptr, UInt64Ptr, Int64Ptr,
UniversalType, STNodePtr, HashtablePtr,
CharPtr, UniversalType, STNodePtr, HashtablePtr,
AutoarrInt8Ptr, AutoarrUInt8Ptr, AutoarrInt16Ptr, AutoarrUInt16Ptr,
AutoarrInt32Ptr, AutoarrUInt32Ptr, AutoarrInt64Ptr, AutoarrUInt64Ptr,
AutoarrUnitypePtr, AutoarrKVPairPtr
@ -46,6 +46,9 @@ typedef struct Unitype{
};
} Unitype;
static const Unitype UniNull={Null,.VoidPtr=NULL};
static const Unitype UniTrue={Bool,.Bool=true};
static const Unitype UniFalse={Bool,.Bool=false};
#define Uni(TYPE,VAL) (Unitype){.type=TYPE,.TYPE=VAL}
#define UniPtr(TYPE,VAL) (Unitype){.type=TYPE,.VoidPtr=VAL}
#define UniNull (Unitype){Null,.VoidPtr=NULL}

View File

@ -1,12 +0,0 @@
#include "base/base.h"
#include "tests/tests.h"
#include "Autoarr/Autoarr2.h"
#include "Hashtable/Hashtable.h"
int main(){
setlocale(LC_ALL, "en-US.Unicode");
printf("\e[92mdtsod parser in c language!\e[97m\n");
optime("test_all",1,{test_all();});
printf("\e[0m\n");
return 0;
}

View File

@ -1,21 +0,0 @@
#pragma once
#include "../base/base.h"
void printuni(Unitype v);
void test_all(void);
void test_searchtree(void);
void test_autoarr2(void);
void test_hashtable(void);
// executes codeblock and prints execution time
// should be used like optime({foo();}), because just optime(foo()) works slower
#define optime(opname,repeats,codeblock) ({\
clock_t start=clock();\
for(uint64 ___OPREP=0;___OPREP<repeats;___OPREP++)\
(codeblock);\
clock_t stop=clock();\
double t=(double)(stop-start)/CLOCKS_PER_SEC/repeats;\
printf("\e[93moperation \e[94m%s\e[93m took \e[94m%lf \e[93mseconds\n",opname,t);\
})

View File

@ -1,3 +1,4 @@
#include "../src/base/base.h"
#include "tests.h"
@ -28,9 +29,19 @@ void printuni(Unitype v){
}
}
void test_all(void){
void test_all(){
test_searchtree();
test_autoarr2();
test_hashtable();
test_string();
test_dtsod();
printf("\e[96m---------------------------------------\e[0m\n");
}
int main(){
setlocale(LC_ALL, "en-US.Unicode");
printf("\e[92mdtsod parser in c language!\e[97m\n");
optime("test_all",1,{test_all();});
printf("\e[0m\n");
return 0;
}

View File

@ -1,5 +1,5 @@
#include "tests.h"
#include "../Autoarr/Autoarr2.h"
#include "../src/Autoarr/Autoarr2.h"
static void printautoarr(Autoarr2(uint16)* ar){
printf("\e[94mAutoarr2(uint16): %lu\n"

19
DtsodC/tests/test_dtsod.c Normal file
View File

@ -0,0 +1,19 @@
#include "tests.h"
#include "../src/DtsodParser/DtsodV24.h"
void test_dtsod(){
optime(__func__,1,({
printf("\e[96m-------------[test_dtsod]-------------\n");
char text[]=
"message:\n"
"{\n"
" type: \"sent\";\n"
" time: \"15.12.2021 20:51:24 +03:00\";\n"
" author_id: 293798876950036480ul;\n"
" channel_id: 913088838761603212ul;\n"
" message_id: 920734809096077353ul;\n"
" text: \"_$\\\"\\\\'''\n\ta ыыы000;2;=:%d;```\";\n"
"};\n";
Hashtable* dtsod=DtsodV24_deserialize(text);
}));
}

View File

@ -1,5 +1,5 @@
#include "tests.h"
#include "../Hashtable/Hashtable.h"
#include "../src/Hashtable/Hashtable.h"
void printkvp(KeyValuePair p){
printf("{\"%s\", ",p.key);
@ -31,9 +31,9 @@ void printrowgraph(Hashtable* ht){
}
for(uint32 i=0; i<lgs_l; i++)
if(lgs[i]>0) {
char* str0=mystrmtpl(' ',i>=100?0:(i>=10?1:2));
char* str1=mystrmtpl(' ',lgs[i]>=100?0:(lgs[i]>=10?1:2));
char* str2=mystrmtpl('#',lgs[i]/100);
char* str0=char_multiply(' ',i>=100?0:(i>=10?1:2));
char* str1=char_multiply(' ',lgs[i]>=100?0:(lgs[i]>=10?1:2));
char* str2=char_multiply('#',lgs[i]/100);
printf("\e[94m length: \e[96m%u %s \e[94mfrequency: \e[96m%u %s \e[90m%s\n",i,str0,lgs[i],str1,str2);
free(str0);
free(str1);
@ -61,7 +61,7 @@ Unitype gett(Hashtable* ht){
}
void test_hashtable(void){
void test_hashtable(){
optime("test_hashtable",1,({
printf("\e[96m-----------[test_hashtable]------------\n");
Hashtable* ht=Hashtable_create();

View File

@ -1,5 +1,5 @@
#include "tests.h"
#include "../SearchTree/SearchTree.h"
#include "../src/SearchTree/SearchTree.h"
void printstnode(STNode* node){
printf("\e[94mSTNode: %lu\n address: %p\n value: ",sizeof(STNode),node);

View File

@ -0,0 +1,16 @@
#include "tests.h"
#include "../src/base/mystr.h"
void test_string(){
optime(__func__,1,({
printf("\e[96m-------------[test_string]-------------\n");
char c[]="0123456789abcdef";
string s=string_cpFromCharPtr(c);
printf("\e[92m\"%s\" -> string_cpFromCharPtr()\n",c);
if(s.length!=16) throw("string created with incorrect length");
char* p=string_cpToCharPtr(s);
printf("\e[92mstring_cpToCharPtr() -> \"%s\"\n",p);
free(p);
free(s.ptr);
}));
}

11
DtsodC/tests/tests.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "../src/base/base.h"
void printuni(Unitype v);
void test_searchtree();
void test_autoarr2();
void test_hashtable();
void test_string();
void test_dtsod();