| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645 |
- /* vim: set filetype=c : */
- #ifndef LIB_H
- # define LIB_H
- # ifndef _STDINT_H
- # define LIB_H_STDINT
- # define intmax_t long int
- # endif /* _STDINT_H */
- # ifndef _UNISTD_H
- # define LIB_H_UNISTD
- # define R_OK 4
- # define W_OK 2
- # define X_OK 1
- # define F_OK 0
- # endif /* _UNISTD_H */
- # ifndef NULL
- # define LIB_H_NULL
- # define NULL ((void *) 0)
- # endif /* NULL */
- # ifndef _STDBOOL_H
- # define LIB_H_STDBOOL
- # define bool unsigned char
- # define true 1
- # define false 0
- # endif /* _STDBOOL_H */
- /* --------------------------- START GLOBAL DEF ---------------------------- */
- # define ALLOC_FUNC void *(*alloc)(u64)
- # define FREE_FUNC void (*free)(void *)
- # define MACRO_STR_CONCAT_X(lhs, rhs) lhs ## rhs
- # define MACRO_STR_CONCAT(lhs, rhs) MACRO_STR_CONCAT_X(lhs, rhs)
- # define MACRO_STR_VALUE(arg) #arg
- # define MACRO_STR_VALUE_X(arg) MACRO_STR_VALUE(arg)
- # define BOOL2CSTR(bool) ((bool) ? "True" : "False")
- # define UNUSED(arg) (void) arg
- enum err {
- ERR_OK = 0,
- ERR_GENERAL_ERROR,
- ERR_NOT_INT,
- ERR_TOO_BIG,
- ERR_NULL_ARG,
- ERR_INVALID_ARG,
- ERR_NOT_FOUND,
- ERR_INDEX_TOO_LARGE,
- ERR_FAILED_OPEN,
- ERR_FAILED_CLOSE,
- ERR_FAILED_READ,
- ERR_FAILED_WRITE,
- ERR_FAILED_FORK,
- ERR_FAILED_WAITPID,
- ERR_WROTE_WRONG_AMOUNT,
- ERR_FAILED_ALLOC,
- ERR_FAILED_REALLOC,
- ERR_MKDIR_FAILED,
- ERR_FAILED_HASHING,
- ERR_STR_EMPTY,
- ERR_PATH_EMPTY,
- ERR_PATH_INVALID,
- ERR_PATH_FILE_EMPTY,
- ERR_PATH_FILE_FAILED_SEEK,
- ERR_CMD_NON_ZERO_EXIT_CODE,
- ERR_SGFX_POS_OUTSIDE_CANVAS
- };
- const char *err_to_name[] = {
- "ERR_OK",
- "ERR_GENERAL_ERROR",
- "ERR_NOT_INT",
- "ERR_TOO_BIG",
- "ERR_NULL_ARG",
- "ERR_INVALID_ARG",
- "ERR_NOT_FOUND",
- "ERR_INDEX_TOO_LARGE",
- "ERR_FAILED_OPEN",
- "ERR_FAILED_CLOSE",
- "ERR_FAILED_READ",
- "ERR_FAILED_WRITE",
- "ERR_FAILED_FORK",
- "ERR_FAILED_WAITPID",
- "ERR_WROTE_WRONG_AMOUNT",
- "ERR_FAILED_ALLOC",
- "ERR_FAILED_REALLOC",
- "ERR_MKDIR_FAILED",
- "ERR_FAILED_HASHING",
- "ERR_STR_EMPTY",
- "ERR_PATH_EMPTY",
- "ERR_PATH_INVALID",
- "ERR_PATH_FILE_EMPTY",
- "ERR_PATH_FILE_FAILED_SEEK",
- "ERR_CMD_NON_ZERO_EXIT_CODE",
- "ERR_SGFX_POS_OUTSIDE_CANVAS",
- };
- /* ---------------------------- END GLOBAL DEF ----------------------------- */
- /* ----------------------------- START INT DEF ----------------------------- */
- typedef long int i64;
- typedef unsigned long int u64;
- typedef int i32;
- typedef unsigned int u32;
- typedef short int i16;
- typedef unsigned short int u16;
- typedef char i8;
- typedef unsigned char u8;
- /* ------------------------------ END INT DEF ------------------------------ */
- void *malloc(u64 size);
- void *realloc(void *ptr, u64 new_size);
- void free(void *ptr);
- void *memcpy(void *dest, const void *src, u64 n);
- void *memset(void *s, int c, u64 n);
- char *getenv(const char *name);
- void abort(void);
- void exit(int exit_code);
- int execve(const char *path, char *const argv[],
- char *const envp[]);
- int fork(void);
- # ifndef WIFEXITED
- # error "Must import <sys/wait.h> before lib.h!"
- # endif
- /* ----------------------------- START LIB DEF ----------------------------- */
- # define TODO(msg) \
- do { \
- fprintf(stderr, "%s:%d "msg"\n", __FILE__, __LINE__); \
- abort(); \
- } while(0);
- # define LIB_COALESCE2(arg1, arg2) ((arg1 != Null) ? arg1 : arg2)
- # define LIB_SET_IF_NULL(var, val) \
- if ( (var) == NULL ) { \
- (var) = (val); \
- }
- # define LIB_SET_IF_NOT_NULL(var, err) \
- if ( var != NULL ) { \
- *var = err; \
- }
- # define LIB_ARG_IF_NOT_NULL_MUST_BE(arg, val, ret_val) \
- if ( arg != NULL ) { \
- if ( *arg != val ) { \
- return ret_val; \
- } \
- }
- # define LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(arg, val) \
- if ( arg != NULL ) { \
- if ( *arg != val ) { \
- return *arg; \
- } \
- }
- # define LIB_ARG_MUST_NOT_BE_NULL_RET_ERR(arg) \
- if ( (arg) == NULL ) { \
- return ERR_NULL_ARG; \
- }
- # define LIB_ARG_MUST_NOT_BE_NULL(arg, err_var, ret_val) \
- if ( (arg) == NULL ) { \
- LIB_SET_IF_NOT_NULL(err_var, ERR_NULL_ARG); \
- return ret_val; \
- }
- # define LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(arg, err_var) \
- if ( (arg) == NULL ) { \
- LIB_SET_IF_NOT_NULL(err_var, ERR_NULL_ARG); \
- return ERR_NULL_ARG; \
- }
- # define LIB_STR_MUST_NOT_BE_EMPTY(arg, err_var, ret_val) \
- if ( (arg).data == NULL || (arg).size == 0 ) { \
- LIB_SET_IF_NOT_NULL(err_var, ERR_STR_EMPTY); \
- return ret_val; \
- }
- # define _r_ __restrict__
- # define SIZEOF_MEMBER(Struct, Member) sizeof(((Struct *)0)->Member)
- # define CAST(Type, Var) ((Type) (Var))
- # define LIB_FREE lib_free
- void lib_free(const void *ptr);
- # if defined(IMP) || defined(IMP_LIB)
- void
- lib_free(const void *ptr)
- {
- if ( ptr == NULL ) return;
- free((void *)ptr);
- }
- # endif /* defined(IMP) || defined(IMP_LIB) */
- /* ------------------------------ END LIB DEF ------------------------------ */
- /* ----------------------------- START VEC DEF ----------------------------- */
- # if defined(WANT_VEC2) || defined(WANT_ALL)
- # define _VEC2_STRUCT_DEF(type) \
- struct MACRO_STR_CONCAT(type, vec2) { \
- type x, y; \
- }; \
- struct MACRO_STR_CONCAT(type, vec2s) { \
- type w, h; \
- }
- _VEC2_STRUCT_DEF(i64);
- _VEC2_STRUCT_DEF(u64);
- _VEC2_STRUCT_DEF(i32);
- _VEC2_STRUCT_DEF(u32);
- _VEC2_STRUCT_DEF(i16);
- _VEC2_STRUCT_DEF(u16);
- _VEC2_STRUCT_DEF(i8);
- _VEC2_STRUCT_DEF(u8);
- # undef _VEC2_STRUCT_DEF
- # endif /* defined(WANT_VEC2) || defined(WANT_ALL) */
- /* ------------------------------ END VEC DEF ------------------------------ */
- /* ---------------------------- START CSTR DEF ----------------------------- */
- # if defined(WANT_CSTR) || defined(WANT_ALL)
- u64 cstr_len_max(const char *cstr, u64 max, bool *out_hit_max,
- enum err *out_err);
- # endif /* defined(WANT_CSTR) || defined(WANT_ALL) */
- /* ----------------------------- END CSTR DEF ------------------------------ */
- /* ---------------------------- START STR DEF ------------------------------ */
- # if defined(WANT_STR) || defined(WANT_ALL)
- # ifndef STR_SIZE_LIMIT
- # define STR_SIZE_LIMIT 1028
- # endif /* STR_SIZE_LIMIT */
- # define STR_DESTROY(Str) \
- if ( (Str).should_be_freed == true ) LIB_FREE((Str).data)
- # define DA2STR(Da, Str) \
- (Str).data = (Da).data; \
- (Str).size = (Da).size; \
- (Str).should_be_freed = true;
- struct str {
- const char *data;
- u64 size;
- bool should_be_freed;
- };
- const struct str STR_EMPTY = {"", 0, false};
- struct str_tokenizer {
- struct str str;
- u64 cur;
- char c;
- bool (*f)(char c);
- };
- struct str str_from_cstr(const char *cstr, u64 cstr_size,
- enum err *out_err);
- struct str str_from_cstr_ns(const char *cstr, enum err *out_err);
- struct str str_from_i64(i64 num, enum err *out_err);
- struct str str_from_i64_temp(i64 num);
- struct str str_dup(struct str str);
- struct str str_replace_escape_chars(const struct str *str, enum err *out_err);
- intmax_t str_to_int(struct str str, enum err *err);
- struct str str_rstrip(struct str str);
- struct str str_lstrip(struct str str);
- struct str str_strip(struct str str);
- u64 str_lindex(struct str str, char c);
- u64 str_rindex(struct str str, char c);
- struct str_tokenizer str_tokenize(struct str str, char c);
- struct str_tokenizer str_tokenize_func(struct str str, bool (*f)(char c));
- struct str str_tokenizer_next(struct str_tokenizer *st);
- struct str str_slice(struct str str, u64 from, u64 to);
- bool str_eq_cstr(struct str str, const char *cstr, u64 cstr_size);
- bool str_eq_str(struct str str1, struct str str2);
- bool str_startswith_cstr(struct str str, const char *cstr, u64 cstr_size);
- bool str_is_int(struct str str);
- struct str_builder {
- char *data;
- u64 size;
- u64 cap;
- };
- struct str str_builder_to_str(const struct str_builder *str_bldr);
- # if defined(IMP) || defined(IMP_STR)
- struct str
- str_replace_escape_chars(const struct str *str, enum err *out_err)
- {
- struct str empty = {0};
- struct str_builder ret = {0};
- u64 i = 0;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- LIB_ARG_MUST_NOT_BE_NULL(str, out_err, empty);
- LIB_STR_MUST_NOT_BE_EMPTY(*str, out_err, empty);
- ret.data = malloc(str->size);
- ret.size = 0;
- if ( ret.data == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- return empty;
- }
- memset((void*)ret.data, 0, str->size);
- for ( i = 0; i < str->size; ++i ) {
- if ( str->data[i] == '\\' ) {
- if ( (i+1) < str->size ) {
- ++i;
- switch ( str->data[i] ) {
- case 'n': ret.data[ret.size++] = '\n'; break;
- case 'r': ret.data[ret.size++] = '\r'; break;
- case 't': ret.data[ret.size++] = '\t'; break;
- case 'e': ret.data[ret.size++] = '\033'; break;
- default: ret.data[ret.size++] = '\\';
- ret.data[ret.size++] = str->data[i];
- break;
- }
- continue;
- }
- }
- ret.data[ret.size++] = str->data[i];
- }
- return str_builder_to_str(&ret);
- }
- # endif /* defined(IMP) || defined(IMP_STR) */
- # endif /* defined(WANT_STR) || defined(WANT_ALL) */
- /* ----------------------------- END STR DEF ------------------------------- */
- /* -------------------------- START DYN ARR DEF ---------------------------- */
- # if defined(WANT_DYN_ARR) || defined(WANT_ALL)
- struct dyn_arr {
- void *data;
- u64 size;
- u64 cap;
- u16 elem_size;
- };
- struct dyn_arr dyn_arr_create(u16 elem_size, enum err *out_err);
- enum err dyn_arr_append(struct dyn_arr *da, void *elem, enum err *out_err);
- enum err dyn_arr_prepend(struct dyn_arr *da, void *elem, enum err *out_err);
- enum err dyn_arr_insert(struct dyn_arr *da, void *elem, u64 index,
- enum err *out_err);
- void *dyn_arr_pop(struct dyn_arr *da, u64 index, enum err *out_err);
- void *dyn_arr_pop_last(struct dyn_arr *da, enum err *out_err);
- enum err dyn_arr_destroy(struct dyn_arr *da, enum err *out_err);
- # if defined(IMP) || defined(IMP_DYN_ARR)
- struct dyn_arr
- dyn_arr_create(u16 elem_size, enum err *out_err)
- {
- struct dyn_arr empty = {0};
- struct dyn_arr da = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- da.size = 0;
- da.cap = 64;
- da.elem_size = elem_size;
- da.data = malloc(da.elem_size * da.cap);
- if ( da.data == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- return empty;
- }
- memset(da.data, 0, elem_size * da.cap);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return da;
- }
- enum err
- dyn_arr_insert(struct dyn_arr *da, void *elem, u64 index, enum err *out_err)
- {
- u64 new_size = 0;
- u64 i = 0;
- u8 *data = NULL;
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(da, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(da->data, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
- new_size = da->size + 1;
- if ( index >= new_size ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_INDEX_TOO_LARGE);
- return ERR_INDEX_TOO_LARGE;
- }
- if ( new_size >= da->cap ) {
- da->cap *= 2;
- da->data = realloc(da->data, da->cap);
- if ( da->data == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- return ERR_FAILED_ALLOC;
- }
- }
- data = (u8*) da->data;
- if ( da->size > 0 ) {
- for ( i = da->size-1; i > index; i-- ) {
- memcpy((data + i), (data + i - 1), da->elem_size);
- }
- }
- memcpy((data + index), elem, da->elem_size);
- ++da->size;
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- enum err
- dyn_arr_append(struct dyn_arr *da, void *elem, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(da, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(da->data, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
- return dyn_arr_insert(da, elem, da->size, out_err);
- }
- enum err
- dyn_arr_prepend(struct dyn_arr *da, void *elem, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(da, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(da->data, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
- return dyn_arr_insert(da, elem, 0, out_err);
- }
- void *
- dyn_arr_pop(struct dyn_arr *da, u64 index, enum err *out_err)
- {
- static u8 temp_mem[256] = {0};
- u8 *data = NULL;
- u64 i = 0;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(da, out_err, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(da->data, out_err, NULL);
- if ( index >= da->size ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_INDEX_TOO_LARGE);
- return NULL;
- }
- data = (u8*) da->data;
- memcpy(temp_mem, (data + index), da->elem_size);
- for ( i = index; i < da->size-1; ++i ) {
- memcpy((data + i), (data + i + 1), da->elem_size);
- }
- --da->size;
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return temp_mem;
- }
- void *
- dyn_arr_pop_last(struct dyn_arr *da, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(da, out_err, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(da->data, out_err, NULL);
- return dyn_arr_pop(da, da->size-1, out_err);
- }
- enum err
- dyn_arr_destroy(struct dyn_arr *da, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(da, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(da->data, out_err);
- free(da->data);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- # endif /* defined(IMP) || defined(IMP_DYN_ARR) */
- # endif /* defined(WANT_DYN_ARR) || defined(WANT_ALL) */
- /* --------------------------- END DYN ARR DEF ----------------------------- */
- /* ---------------------------- START DA DEF ------------------------------- */
- # define DA_FOREACH(Da, Var) \
- for ( typeof((Da).data) (Var) = (Da).data; \
- (Var) < ((Da).data + (Da).size); \
- ++(Var) )
- # define DA_FOREACH_INDEX(Da, VarI) \
- for ( typeof((Da).size) (VarI) = 0; \
- (VarI) < (Da).size; \
- ++(VarI) )
- # define DA_APPEND(da, val, err_var) \
- do { \
- if ( err_var != NULL ) { \
- if ( *err_var != ERR_OK ) { \
- break; \
- } \
- } \
- if ( (da).size + 1 >= (da).cap ) { \
- (da).cap *= 2; \
- (da).data = realloc((da).data, (da).cap); \
- if ( (da).data == NULL ) { \
- LIB_SET_IF_NOT_NULL((err_var), ERR_FAILED_REALLOC); \
- break; \
- } \
- } \
- if ( (da).data == NULL ) { \
- if ( (da).cap == 0 ) { \
- (da).cap = 32; \
- (da).size = 0; \
- } \
- (da).data = malloc(sizeof(*(da).data) * (da).cap); \
- if ( (da).data == NULL ) { \
- LIB_SET_IF_NOT_NULL((err_var), ERR_FAILED_ALLOC); \
- break; \
- } \
- memset((da).data, 0, sizeof(*(da).data) * (da).cap); \
- } \
- (da).data[(da).size++] = (val); \
- LIB_SET_IF_NOT_NULL((err_var), ERR_OK); \
- } while(0)
- # define DA_APPEND_DATA(Da, Val, ItemNum, ErrVar) \
- do { \
- if ( (ErrVar) != NULL ) { \
- if ( *(ErrVar) != ERR_OK ) { \
- break; \
- } \
- } \
- if ( (Da).size + (ItemNum) >= (Da).cap ) { \
- (Da).cap += (ItemNum); \
- (Da).cap *= 2; \
- (Da).data = realloc((Da).data, (Da).cap); \
- if ( (Da).data == NULL ) { \
- LIB_SET_IF_NOT_NULL((ErrVar), ERR_FAILED_REALLOC); \
- break; \
- } \
- } \
- if ( (Da).data == NULL ) { \
- if ( (Da).cap == 0 ) { \
- (Da).cap = (ItemNum) * 2; \
- (Da).size = 0; \
- } \
- (Da).data = malloc(sizeof(*(Da).data) * (Da).cap); \
- if ( (Da).data == NULL ) { \
- LIB_SET_IF_NOT_NULL((ErrVar), ERR_FAILED_ALLOC); \
- break; \
- } \
- } \
- memcpy((Da).data, (Val), sizeof(*(Da).data) * (ItemNum)); \
- (Da).size += ItemNum; \
- LIB_SET_IF_NOT_NULL((ErrVar), ERR_OK); \
- } while(0)
- # define DAV_APPEND(Da, Val, ValSize, ErrVar) \
- do { \
- if ( ErrVar != NULL ) { \
- if ( *ErrVar != ERR_OK ) { \
- break; \
- } \
- } \
- /* printf("ValSize -> %5ld\tused_bytes -> %5ld\tcap_bytes -> %5ld\n", (ValSize), (Da).used_bytes, (Da).cap_bytes); */ \
- if ( (Da).used_bytes + (ValSize) >= (Da).cap_bytes ) { \
- (Da).cap_bytes *= 2; \
- (Da).data = realloc((Da).data, (Da).cap_bytes); \
- if ( (Da).data == NULL ) { \
- LIB_SET_IF_NOT_NULL((ErrVar), ERR_FAILED_REALLOC); \
- break; \
- } \
- } \
- if ( (Da).data == NULL ) { \
- if ( (Da).cap_bytes == 0 ) { \
- (Da).cap_bytes = 32; \
- (Da).size = 0; \
- (Da).used_bytes = 0; \
- } \
- (Da).data = malloc(sizeof(u64) * (Da).cap_bytes); \
- if ( (Da).data == NULL ) { \
- LIB_SET_IF_NOT_NULL((ErrVar), ERR_FAILED_ALLOC); \
- break; \
- } \
- } \
- memcpy(CAST(u8*, (Da).data) + (Da).used_bytes, (Val), (ValSize)); \
- (Da).used_bytes += (ValSize); \
- ++(Da).size; \
- LIB_SET_IF_NOT_NULL((ErrVar), ERR_OK); \
- } while(0)
- /* ----------------------------- END DA DEF -------------------------------- */
- /* ---------------------------- START MAP DEF ------------------------------ */
- # if defined(WANT_MAP) || defined(WANT_ALL)
- # define MAP_FOR_EACH(Map, VIndex, VKey) \
- for ( (VIndex = (Map)->indexs.data, VKey = (Map)->keys.data); \
- VIndex < ((Map)->indexs.data + (Map)->indexs.size); \
- (++VIndex, VKey = CAST(struct key_bytes *, CAST(u8*, VKey->key) + VKey->size)) )
- # define MAP_FOR_EACH_INDEXS(Map, Var) \
- for ( Var = (Map)->indexs.data; \
- Var < ((Map)->indexs.data + (Map)->indexs.size); \
- ++Var )
- # define MAP_GET_INDEX(Map, Index) \
- ((struct map_item *)(((u8*)(Map)->data) + ((Map)->_item_size * (Index))))
- struct key_bytes {
- u64 size;
- u8 key[1];
- };
- struct map_item {
- u64 key[4];
- u8 item[1];
- };
- struct map {
- struct map_item *data;
- u64 size;
- struct {
- u64 *data;
- u64 size;
- u64 cap;
- } indexs;
- struct {
- struct key_bytes *data;
- u64 size;
- u64 used_bytes;
- u64 cap_bytes;
- } keys;
- u64 _cap;
- u64 _size_bytes;
- u64 _item_size;
- u64 _elem_size;
- u64 *(*hash)(void *key, u64 key_size);
- };
- struct map map_create(u64 elem_size, u64 cap, enum err *_r_ out_err);
- enum err map_inc_cap(struct map *_r_ m, enum err *_r_ out_err);
- enum err map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
- enum err *_r_ out_err);
- enum err map_add(struct map *_r_ m, void *_r_ key, u64 key_size, void *_r_ elem,
- enum err *_r_ out_err);
- void *map_get(struct map *_r_ m, void *_r_ key, u64 key_size, enum err *_r_ out_err);
- enum err map_set_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
- enum err *_r_ out_err);
- enum err map_set(struct map *_r_ m, void *_r_ key, u64 key_size,
- void *_r_ elem, enum err *_r_ out_err);
- void *map_pop(struct map *_r_ m, void *_r_ key, u64 key_size, enum err *_r_ out_err);
- enum err map_destroy(struct map *_r_ m, enum err *_r_ out_err);
- u64 *map_default_hasher(void *key, u64 key_size);
- # if defined(IMP) || defined(IMP_MAP)
- struct map
- map_create(u64 elem_size, u64 cap, enum err *out_err)
- {
- struct map empty = {0};
- struct map m = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- m._cap = cap;
- m._elem_size = elem_size;
- m._item_size = SIZEOF_MEMBER(struct map_item, key) + m._elem_size + 1;
- m._size_bytes = m._item_size * m._cap;
- m.data = malloc(m._size_bytes);
- if ( m.data == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- goto err_exit;
- }
- memset(m.data, 0, m._size_bytes);
- m.indexs.cap = m._cap;
- m.indexs.data = malloc(sizeof(*m.indexs.data) * m.indexs.cap);
- if ( m.indexs.data == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- goto err_exit;
- }
- memset(m.indexs.data, 0, sizeof(*m.indexs.data) * m.indexs.cap);
- m.keys.cap_bytes = m._cap;
- m.keys.data = malloc(sizeof(u64) * m.keys.cap_bytes);
- if ( m.keys.data == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- goto err_exit;
- }
- memset(m.keys.data, 0, m.keys.cap_bytes);
- m.hash = map_default_hasher;
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return m;
- err_exit:
- if ( m.data != NULL ) free(m.data);
- if ( m.indexs.data != NULL ) free(m.indexs.data);
- if ( m.keys.data != NULL ) free(m.keys.data);
- return empty;
- }
- enum err
- map_inc_cap(struct map *_r_ m, enum err *_r_ out_err)
- {
- enum err err = ERR_OK;
- enum err *perr = &err;
- struct map old = {0};
- struct map nm = {0};
- u64 *index = 0;
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m , out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
- if ( out_err != NULL ) {
- perr = out_err;
- }
- nm = map_create(m->_elem_size, (m->_cap * 2), perr);
- if ( *perr != ERR_OK ) {
- goto err_exit;
- }
- MAP_FOR_EACH_INDEXS(m, index) {
- struct map_item *mi = MAP_GET_INDEX(m, (*index));
- map_add_hashed_key(&nm, mi->key, mi->item, perr);
- if ( *perr != ERR_OK ) {
- goto err_exit;
- }
- }
- old = *m;
- m->data = nm.data;
- m->size = nm.size;
- m->indexs = nm.indexs;
- m->keys = nm.keys;
- m->_cap = nm._cap;
- m->_size_bytes = nm._size_bytes;
- m->_item_size = nm._item_size;
- m->_elem_size = nm._elem_size;
- m->hash = nm.hash;
- map_destroy(&old, NULL);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- err_exit:
- map_destroy(&nm, NULL);
- return *perr;
- }
- enum err
- map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
- enum err *_r_ out_err)
- {
- enum err err = ERR_OK;
- enum err *perr = &err;
- u64 i = 0;
- struct map_item *it = NULL;
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
- if ( out_err != NULL ) {
- perr = out_err;
- }
- i = (key[0] + key[1] + key[2] + key[3]) % m->_cap;
- do {
- if ( i >= m->_cap ) {
- map_inc_cap(m, perr);
- if ( *perr != ERR_OK ) {
- return *perr;
- }
- }
- it = MAP_GET_INDEX(m, i++);
- } while (it->key[0] != 0 || it->key[1] != 0
- || it->key[2] != 0 || it->key[3] != 0);
- /*
- printf("cap=%-5ld\telem_size=%-5ld\tsize_bytes=%-5ld\n",
- m->_cap, m->_elem_size, m->_size_bytes);
- */
- memcpy(it->key, key, sizeof(u64) * 4);
- memcpy(it->item, elem, m->_elem_size);
- DA_APPEND(m->indexs, i-1, perr);
- if ( *perr != ERR_OK ) {
- memset(it->key, 0, sizeof(u64) * 4);
- memset(it->item, 0, m->_elem_size);
- return *perr;
- }
- *perr = ERR_OK;
- return ERR_OK;
- }
- enum err
- map_add(struct map *m, void *key, u64 key_size, void *elem, enum err *out_err)
- {
- enum err err = ERR_OK;
- enum err *perr = &err;
- struct key_bytes *sb = NULL;
- u64 *hash = NULL;
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
- if ( out_err != NULL ) {
- perr = out_err;
- }
- hash = m->hash(key, key_size);
- if ( hash == NULL ) {
- *perr = ERR_FAILED_HASHING;
- return *perr;
- }
- map_add_hashed_key(m, hash, elem, perr);
- free(hash);
- if ( *perr != ERR_OK ) {
- return *perr;
- }
- sb = malloc(SIZEOF_MEMBER(struct key_bytes, size) + key_size);
- if ( sb == NULL ) {
- *perr = ERR_FAILED_ALLOC;
- return *perr;
- }
- memset(sb, 0, SIZEOF_MEMBER(struct key_bytes, size) + key_size);
- sb->size = key_size;
- memcpy(sb->key, key, key_size);
- DAV_APPEND(
- m->keys, sb,
- SIZEOF_MEMBER(struct key_bytes, size) + key_size,
- perr
- );
- /*
- do {
- if (perr != ((void * ) 0)) {
- if ( * perr != ERR_OK) {
- break;
- }
- }
- if ((m -> keys).used_bytes + (sizeof(((struct key_bytes * ) 0) -> size) + key_size) >= (m -> keys).cap_bytes) {
- (m -> keys).cap_bytes *= 2;
- (m -> keys).data = realloc((m -> keys).data, (m -> keys).cap_bytes);
- if ((m -> keys).data == ((void * ) 0)) {
- if ((perr) != ((void * ) 0)) {
- *(perr) = ERR_FAILED_REALLOC;
- };
- break;
- }
- }
- if ((m -> keys).data == ((void * ) 0)) {
- if ((m -> keys).cap_bytes == 0) {
- (m -> keys).cap_bytes = 32;
- (m -> keys).size = 0;
- (m -> keys).used_bytes = 0;
- }(m -> keys).data = malloc(sizeof(u64) * (m -> keys).cap_bytes);
- if ((m -> keys).data == ((void * ) 0)) {
- if ((perr) != ((void * ) 0)) {
- *(perr) = ERR_FAILED_ALLOC;
- };
- break;
- }
- }
- memcpy(((u8 * )((m -> keys).data)) + (m -> keys).used_bytes, (sb), (sizeof(((struct key_bytes * ) 0) -> size) + key_size));
- (m -> keys).used_bytes += (sizeof(((struct key_bytes * ) 0) -> size) + key_size);
- ++(m -> keys).size;
- if ((perr) != ((void * ) 0)) {
- *(perr) = ERR_OK;
- };
- } while (0);
- */
- free(sb);
- if ( *perr != ERR_OK ) {
- return *perr;
- }
- *perr = ERR_OK;
- return ERR_OK;
- }
- void *
- map_get(struct map *m, void *key, u64 key_size, enum err *out_err)
- {
- u64 i = 0;
- struct map_item *it = NULL;
- u64 *hash = NULL;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(m , out_err, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(m->data, out_err, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(key , out_err, NULL);
- hash = m->hash(key, key_size);
- i = (hash[0] + hash[1] + hash[2] + hash[3]) % m->_cap;
- do {
- if ( i >= m->_cap ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_NOT_FOUND);
- free(hash);
- return NULL;
- }
- it = MAP_GET_INDEX(m, i++);
- } while (it->key[0] != hash[0] || it->key[1] != hash[1]
- || it->key[2] != hash[2] || it->key[3] != hash[3]);
- free(hash);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return it->item;
- }
- enum err
- map_set_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
- enum err *_r_ out_err)
- {
- enum err err = ERR_OK;
- enum err *perr = &err;
- u64 i = 0;
- struct map_item *it = NULL;
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
- if ( out_err != NULL ) {
- perr = out_err;
- }
- i = (key[0] + key[1] + key[2] + key[3]) % m->_cap;
- do {
- if ( i >= m->_cap ) {
- *perr = ERR_NOT_FOUND;
- return *perr;
- }
- it = MAP_GET_INDEX(m, i++);
- } while (it->key[0] != key[0] || it->key[1] != key[1]
- || it->key[2] != key[2] || it->key[3] != key[3]);
- memcpy(it->item, elem, m->_elem_size);
- *perr = ERR_OK;
- return ERR_OK;
- }
- enum err
- map_set(struct map *_r_ m, void *_r_ key, u64 key_size, void *_r_ elem,
- enum err *_r_ out_err)
- {
- enum err err = ERR_OK;
- enum err *perr = &err;
- u64 *hash = NULL;
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
- if ( out_err != NULL ) {
- perr = out_err;
- }
- hash = m->hash(key, key_size);
- if ( hash == NULL ) {
- *perr = ERR_FAILED_HASHING;
- return *perr;
- }
- map_set_hashed_key(m, hash, elem, perr);
- if ( *perr != ERR_OK ) {
- free(hash);
- return *perr;
- }
- free(hash);
- *perr = ERR_OK;
- return ERR_OK;
- }
- void *map_pop(struct map *m, void *key, u64 key_size, enum err *out_err);
- enum err
- map_destroy(struct map *m, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
- if ( m->data != NULL ) free(m->data);
- if ( m->indexs.data != NULL ) free(m->indexs.data);
- if ( m->keys.data != NULL ) free(m->keys.data);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- u64 *
- map_default_hasher(void *key, u64 key_size)
- {
- u64 i = 0;
- u64 *k = NULL;
- k = malloc(sizeof(u64) * 4);
- if ( k == NULL ) {
- return NULL;
- }
- k[0] = 0;
- k[1] = 0;
- k[2] = 0;
- k[3] = 0;
- for ( i = 0; i < key_size; ++i ) {
- k[0] += ((u8*)key)[i] * 31;
- k[1] += ((u8*)key)[i] * 127;
- k[2] += ((u8*)key)[i] * 233;
- k[3] += ((u8*)key)[i] * 353;
- }
- return k;
- }
- # endif /* defined(IMP) || defined(IMP_MAP) */
- # endif /* defined(WANT_MAP) || defined(WANT_ALL) */
- /* ----------------------------- END MAP DEF ------------------------------- */
- /* ---------------------------- START ENV DEF ------------------------------ */
- # if defined(WANT_ENV) || defined(WANT_ALL)
- struct str getenv_as_str(const char *env, enum err *out_err);
- struct path getenv_as_path(const char *env, enum err *out_err);
- # endif /* defined(WANT_ENV) || defined(WANT_ALL) */
- /* ----------------------------- END ENV DEF ------------------------------- */
- /* ---------------------------- START PATH DEF ----------------------------- */
- # if defined(WANT_PATH) || defined(WANT_ALL)
- # ifndef PATH_SIZE_LIMIT
- # define PATH_SIZE_LIMIT 1024
- # endif /* PATH_SIZE_LIMIT */
- struct path {
- char data[PATH_SIZE_LIMIT];
- u64 size;
- };
- struct path path_from_str(struct str str, enum err *out_err);
- struct path path_from_cstr(const char *cstr, u64 cstr_size, enum err *out_err);
- struct path path_from_cstr_ns(const char *cstr, enum err *out_err);
- struct path path_get_xdg_state_home(enum err *out_err);
- struct path path_get_xdg_data_home(enum err *out_err);
- struct path path_dirname(struct path path, enum err *out_err);
- struct path path_join(struct path lhs, struct path rhs, enum err *out_err);
- struct path path_join_with_str(struct path lhs, struct str rhs,
- enum err *out_err);
- struct path path_join_with_cstr(struct path lhs,
- const char *rhs, u64 rhs_size,
- enum err *out_err);
- struct path path_join_with_cstr_ns(struct path lhs, const char *rhs,
- enum err *out_err);
- bool path_exists(struct path path, int (*access)(const char *, int));
- bool path_can_read(struct path path, int (*access)(const char *, int));
- bool path_can_write(struct path path, int (*access)(const char *, int));
- bool path_can_execute(struct path path, int (*access)(const char *, int));
- bool path_mkdir(struct path path, u32 mode, bool do_create_parents,
- int (*mkdir)(const char *, u32), enum err *out_err);
- bool path_touch(struct path path, int (*open)(const char *, int),
- enum err *out_err);
- struct file {
- u8 *data;
- u64 size;
- };
- struct file path_file_read_all(const struct path *path, enum err *out_err);
- enum err path_file_save(const struct path *path, const struct file *file,
- enum err *out_err);
- # endif /* defined(WANT_PATH) || defined(WANT_ALL) */
- /* ----------------------------- END PATH DEF ------------------------------ */
- /* ------------------------- START TOKENIZER DEF --------------------------- */
- # if defined(WANT_TOKENIZER) || defined(WANT_ALL)
- struct tokenizer;
- struct tokenizer_options {
- bool (*skip_token)(struct tokenizer *tkn, char c);
- bool (*is_id)(struct tokenizer *tkn, char c);
- bool (*is_id_start)(struct tokenizer *tkn, char c);
- bool (*is_digit)(struct tokenizer *tkn, char c);
- bool (*is_num_lit)(struct tokenizer *tkn, struct str str);
- bool (*is_str_lit_start)(struct tokenizer *tkn, char c);
- bool (*is_str_lit_end)(struct tokenizer *tkn, char c);
- bool (*is_str_lit)(struct tokenizer *tkn, struct str str);
- };
- enum tokenizer_loc_format {
- TLF_VIM = 0
- };
- enum token_type {
- TK_INVALID = -2,
- TK_EOF = -1,
- TK_NUL = '\0',
- TK_NL = '\n',
- TK_TAB = '\t',
- TK_SPACE = ' ',
- TK_ASTERISK = '*',
- TK_AMPERSAND = '&',
- TK_PLUS = '+',
- TK_MINUS = '-',
- TK_EQUAL = '=',
- TK_SLASH = '/',
- TK_BACKSLASH = '\\',
- TK_POUND = '#',
- TK_SEMICOLON = ';',
- TK_COLON = ':',
- TK_COMMA = ',',
- TK_DOT = '.',
- TK_UNDERSCORE = '_',
- TK_L_BRACES = '(',
- TK_R_BRACES = ')',
- TK_L_BRACKET = '[',
- TK_R_BRACKET = ']',
- TK_L_CUR_BRACES = '{',
- TK_R_CUR_BRACES = '}',
- TK_L_ANG_BRACKET = '<',
- TK_R_ANG_BRACKET = '>',
- TK_SINGLE_QUOTE = '\'',
- TK_DOUBLE_QUOTE = '"',
- TK_BACKTICK = '`',
- TK_TILDE = '~',
- TK_a = 'a',
- TK_b = 'b',
- TK_c = 'c',
- TK_d = 'd',
- TK_e = 'e',
- TK_f = 'f',
- TK_g = 'g',
- TK_h = 'h',
- TK_i = 'i',
- TK_j = 'j',
- TK_k = 'k',
- TK_l = 'l',
- TK_m = 'm',
- TK_n = 'n',
- TK_o = 'o',
- TK_p = 'p',
- TK_q = 'q',
- TK_r = 'r',
- TK_s = 's',
- TK_t = 't',
- TK_u = 'u',
- TK_v = 'v',
- TK_w = 'w',
- TK_x = 'x',
- TK_y = 'y',
- TK_z = 'z',
- TK_A = 'A',
- TK_B = 'B',
- TK_C = 'C',
- TK_D = 'D',
- TK_E = 'E',
- TK_F = 'F',
- TK_G = 'G',
- TK_H = 'H',
- TK_I = 'I',
- TK_J = 'J',
- TK_K = 'K',
- TK_L = 'L',
- TK_M = 'M',
- TK_N = 'N',
- TK_O = 'O',
- TK_P = 'P',
- TK_Q = 'Q',
- TK_R = 'R',
- TK_S = 'S',
- TK_T = 'T',
- TK_U = 'U',
- TK_V = 'V',
- TK_W = 'W',
- TK_X = 'X',
- TK_Y = 'Y',
- TK_Z = 'Z',
- TK_0 = '0',
- TK_1 = '1',
- TK_2 = '2',
- TK_3 = '3',
- TK_4 = '4',
- TK_5 = '5',
- TK_6 = '6',
- TK_7 = '7',
- TK_8 = '8',
- TK_9 = '9',
- TK_ID = 257,
- TK_NUM_LIT,
- TK_STR_LIT,
- TK_LAST = 512
- };
- struct token {
- enum token_type type;
- u64 loc_start;
- u64 loc_end;
- struct str string;
- void *extra; /* This is not used by the lib */
- };
- struct tokenizer {
- u64 i;
- struct tokenizer_options opts;
- struct token last;
- struct path src;
- struct str code;
- void *edata; /* This is not used by the lib */
- };
- struct tokenizer tokenizer_create(struct str code, struct path src,
- struct tokenizer_options *opts,
- enum err *out_err);
- /* In normal use this function does not fail! */
- struct token tokenizer_next_token(struct tokenizer *tkn, enum err *out_err);
- enum token_type tokenizer_next_token_type(struct tokenizer *tkn,
- enum err *out_err);
- struct token tokenizer_peek_token(struct tokenizer *tkn, enum err *out_err);
- enum token_type tokenizer_peek_token_type(struct tokenizer *tkn,
- enum err *out_err);
- bool tokenizer_is_next(struct tokenizer *tkn, enum token_type type,
- struct token *out_tk, enum err *out_err);
- bool tokenizer_is_next_id(struct tokenizer *tkn, struct str string,
- struct token *out_tk, enum err *out_err);
- enum err tokenizer_destroy(struct tokenizer *tkn, enum err *out_err);
- const char *tokenizer_token_loc_temp(const struct tokenizer *tkn,
- const struct token *tk,
- enum tokenizer_loc_format format,
- enum err *out_err);
- const char *token_to_cstr(enum token_type type);
- struct tokenizer_options tokenizer_options_defaultlyzer(
- struct tokenizer_options *tkn_opts);
- bool tokenizer_skip_token(struct tokenizer *tkn, char c);
- bool tokenizer_is_id(struct tokenizer *tkn, char c);
- bool tokenizer_is_id_start(struct tokenizer *tkn, char c);
- bool tokenizer_is_digit(struct tokenizer *tkn, char c);
- bool tokenizer_is_num_lit(struct tokenizer *tkn, struct str str);
- bool tokenizer_is_str_lit_start(struct tokenizer *tkn, char c);
- bool tokenizer_is_str_lit_end(struct tokenizer *tkn, char c);
- bool tokenizer_is_str_lit(struct tokenizer *tkn, struct str str);
- # if defined(IMP) || defined(IMP_TOKENIZER)
- struct tokenizer
- tokenizer_create(struct str code, struct path src,
- struct tokenizer_options *opts, enum err *out_err)
- {
- struct tokenizer empty = {0};
- struct tokenizer tkn = {0};
- struct tokenizer_options defs = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- if ( opts == NULL ) {
- tkn.opts = defs;
- } else {
- tkn.opts = *opts;
- }
- tkn.opts = tokenizer_options_defaultlyzer(&tkn.opts);
- tkn.i = 0;
- tkn.code = code;
- tkn.src = src;
- return tkn;
- }
- struct token
- tokenizer_next_token(struct tokenizer *tkn, enum err *out_err)
- {
- static struct {
- char data[256];
- u16 size;
- } buf = {0};
- struct token empty = {0};
- struct token tk = {0};
- char c = 0;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- LIB_ARG_MUST_NOT_BE_NULL(tkn, out_err, empty);
- buf.size = 0;
- if ( tkn->i >= tkn->code.size ) {
- goto eof_tk;
- }
- c = tkn->code.data[tkn->i++];
- while ( tkn->opts.skip_token(tkn, c) == true ) {
- c = tkn->code.data[tkn->i++];
- }
- if ( tkn->opts.is_id_start(tkn, c) == true ) {
- tk.type = TK_ID;
- tk.loc_start = tkn->i-1;
- do {
- buf.data[buf.size++] = c;
- c = tkn->code.data[tkn->i++];
- } while ( tkn->opts.is_id(tkn, c) == true );
- --tkn->i;
- tk.string.data = buf.data;
- tk.string.size = buf.size;
- if ( tkn->opts.is_num_lit(tkn, tk.string) == true ) {
- tk.type = TK_NUM_LIT;
- }
- tk.loc_end = tkn->i-1;
- goto exit;
- }
- if ( tkn->opts.is_digit(tkn, c) == true ) {
- tk.type = TK_NUM_LIT;
- tk.loc_start = tkn->i-1;
- do {
- buf.data[buf.size++] = c;
- c = tkn->code.data[tkn->i++];
- } while ( tkn->opts.is_digit(tkn, c) == true );
- --tkn->i;
- tk.string.data = buf.data;
- tk.string.size = buf.size;
- tk.loc_end = tkn->i-1;
- goto exit;
- }
- if ( tkn->opts.is_str_lit_start(tkn, c) == true ) {
- tk.type = TK_STR_LIT;
- tk.loc_start = tkn->i-1;
- do {
- buf.data[buf.size++] = c;
- c = tkn->code.data[tkn->i++];
- } while ( tkn->opts.is_str_lit_end(tkn, c) == false );
- buf.data[buf.size++] = c;
- tk.string.data = buf.data;
- tk.string.size = buf.size - 1;
- tk.loc_end = tkn->i-1;
- goto exit;
- }
- tk.type = c;
- if ( tkn->i >= tkn->code.size ) {
- eof_tk:
- tk.type = TK_EOF;
- }
- tk.loc_start = tkn->i-1;
- tk.loc_end = tkn->i-1;
- exit:
- tkn->last = tk;
- return tk;
- }
- enum token_type
- tokenizer_next_token_type(struct tokenizer *tkn, enum err *out_err)
- {
- struct token tk = {0};
- enum err err = ERR_OK;
- enum err *perr = &err;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, TK_INVALID);
- LIB_ARG_MUST_NOT_BE_NULL(tkn, out_err, TK_INVALID);
- if ( out_err != NULL ) {
- perr = out_err;
- }
- tk = tokenizer_next_token(tkn, perr);
- if ( *perr != ERR_OK ) {
- return TK_INVALID;
- }
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return tk.type;
- }
- struct token
- tokenizer_peek_token(struct tokenizer *tkn, enum err *out_err)
- {
- enum err err = ERR_OK;
- enum err *perr = &err;
- u64 last_i = 0;
- struct token empty = {0};
- struct token tk = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- LIB_ARG_MUST_NOT_BE_NULL(tkn, out_err, empty);
- if ( out_err != NULL ) {
- perr = out_err;
- }
- last_i = tkn->i;
- tk = tokenizer_next_token(tkn, perr);
- tkn->i = last_i;
- return tk;
- }
- enum token_type
- tokenizer_peek_token_type(struct tokenizer *tkn, enum err *out_err)
- {
- enum err err = ERR_OK;
- enum err *perr = &err;
- struct token tk = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, TK_INVALID);
- LIB_ARG_MUST_NOT_BE_NULL(tkn, out_err, TK_INVALID);
- tk = tokenizer_peek_token(tkn, perr);
- return tk.type;
- }
- bool
- tokenizer_is_next(struct tokenizer *tkn, enum token_type type,
- struct token *out_tk, enum err *out_err)
- {
- enum err err = ERR_OK;
- struct token tk = {0};
- u64 pi = 0;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, false);
- LIB_ARG_MUST_NOT_BE_NULL(tkn, out_err, false);
- pi = tkn->i;
- tk = tokenizer_next_token(tkn, &err);
- if ( tk.type != type ) {
- tkn->i = pi;
- return false;
- }
- LIB_SET_IF_NOT_NULL(out_tk, tk);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return true;
- }
- bool
- tokenizer_is_next_id(struct tokenizer *tkn, struct str string,
- struct token *out_tk, enum err *out_err)
- {
- enum err err = ERR_OK;
- struct token tk = {0};
- u64 pi = 0;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, false);
- LIB_ARG_MUST_NOT_BE_NULL(tkn, out_err, false);
- LIB_STR_MUST_NOT_BE_EMPTY(string, out_err, false);
- pi = tkn->i;
- tk = tokenizer_next_token(tkn, &err);
- if ( tk.type != TK_ID ) {
- tkn->i = pi;
- return false;
- }
- if ( str_eq_str(tk.string, string) == false ) {
- tkn->i = pi;
- return false;
- }
- LIB_SET_IF_NOT_NULL(out_tk, tk);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return true;
- }
- enum err tokenizer_destroy(struct tokenizer *tkn, enum err *out_err);
- const char *
- tokenizer_token_loc_temp(const struct tokenizer *tkn, const struct token *tk,
- enum tokenizer_loc_format format, enum err *out_err)
- {
- static struct {
- char data[1024];
- u64 size;
- } buf = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(tkn, out_err, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(tk, out_err, NULL);
- buf.size = 0;
- switch ( format ) {
- case TLF_VIM: {
- u64 col = 0;
- memcpy(buf.data, tkn->src.data, tkn->src.size);
- buf.size += tkn->src.size;
- buf.data[buf.size++] = ':';
- {
- u64 i = 0;
- u64 line = 0;
- struct str line_str = {0};
- for ( i = 0; i < tk->loc_start; ++i ) {
- line += ( tkn->code.data[i] == '\n' );
- }
- line_str = str_from_i64_temp((i64)line);
- memcpy(buf.data + buf.size, line_str.data, line_str.size);
- buf.size += line_str.size;
- /* Col values wrong */
- while ( tkn->code.data[i] != '\n' && i > 0 ) {
- --i;
- }
- col = tk->loc_start - i;
- }
- buf.data[buf.size++] = ':';
- {
- struct str col_str = {0};
- col_str = str_from_i64_temp((i64)col);
- memcpy(buf.data + buf.size, col_str.data, col_str.size);
- buf.size += col_str.size;
- }
- buf.data[buf.size++] = ':';
- buf.data[buf.size++] = 0;
- } break;
- default:
- LIB_SET_IF_NOT_NULL(out_err, ERR_INVALID_ARG);
- return NULL;
- }
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return buf.data;
- }
- const char *
- token_to_cstr(enum token_type type)
- {
- switch ( type ) {
- case TK_INVALID: return "TK_INVALID";
- case TK_EOF: return "TK_EOF";
- case TK_NUL: return "TK_NUL";
- case TK_NL: return "TK_NL";
- case TK_TAB: return "TK_TAB";
- case TK_SPACE: return "TK_SPACE";
- case TK_ASTERISK: return "TK_ASTERISK";
- case TK_AMPERSAND: return "TK_AMPERSAND";
- case TK_PLUS: return "TK_PLUS";
- case TK_MINUS: return "TK_MINUS";
- case TK_EQUAL: return "TK_EQUAL";
- case TK_SLASH: return "TK_SLASH";
- case TK_BACKSLASH: return "TK_BACKSLASH";
- case TK_POUND: return "TK_POUND";
- case TK_SEMICOLON: return "TK_SEMICOLON";
- case TK_COLON: return "TK_COLON";
- case TK_COMMA: return "TK_COMMA";
- case TK_DOT: return "TK_DOT";
- case TK_UNDERSCORE: return "TK_UNDERSCORE";
- case TK_L_BRACES: return "TK_L_BRACES";
- case TK_R_BRACES: return "TK_R_BRACES";
- case TK_L_BRACKET: return "TK_L_BRACKET";
- case TK_R_BRACKET: return "TK_R_BRACKET";
- case TK_L_CUR_BRACES: return "TK_L_CUR_BRACES";
- case TK_R_CUR_BRACES: return "TK_R_CUR_BRACES";
- case TK_L_ANG_BRACKET: return "TK_L_ANG_BRACKET";
- case TK_R_ANG_BRACKET: return "TK_R_ANG_BRACKET";
- case TK_SINGLE_QUOTE: return "TK_SINGLE_QUOTE";
- case TK_DOUBLE_QUOTE: return "TK_DOUBLE_QUOTE";
- case TK_BACKTICK: return "TK_BACKTICK";
- case TK_TILDE: return "TK_TILDE";
- case TK_a: return "TK_a";
- case TK_b: return "TK_b";
- case TK_c: return "TK_c";
- case TK_d: return "TK_d";
- case TK_e: return "TK_e";
- case TK_f: return "TK_f";
- case TK_g: return "TK_g";
- case TK_h: return "TK_h";
- case TK_i: return "TK_i";
- case TK_j: return "TK_j";
- case TK_k: return "TK_k";
- case TK_l: return "TK_l";
- case TK_m: return "TK_m";
- case TK_n: return "TK_n";
- case TK_o: return "TK_o";
- case TK_p: return "TK_p";
- case TK_q: return "TK_q";
- case TK_r: return "TK_r";
- case TK_s: return "TK_s";
- case TK_t: return "TK_t";
- case TK_u: return "TK_u";
- case TK_v: return "TK_v";
- case TK_w: return "TK_w";
- case TK_x: return "TK_x";
- case TK_y: return "TK_y";
- case TK_z: return "TK_z";
- case TK_A: return "TK_A";
- case TK_B: return "TK_B";
- case TK_C: return "TK_C";
- case TK_D: return "TK_D";
- case TK_E: return "TK_E";
- case TK_F: return "TK_F";
- case TK_G: return "TK_G";
- case TK_H: return "TK_H";
- case TK_I: return "TK_I";
- case TK_J: return "TK_J";
- case TK_K: return "TK_K";
- case TK_L: return "TK_L";
- case TK_M: return "TK_M";
- case TK_N: return "TK_N";
- case TK_O: return "TK_O";
- case TK_P: return "TK_P";
- case TK_Q: return "TK_Q";
- case TK_R: return "TK_R";
- case TK_S: return "TK_S";
- case TK_T: return "TK_T";
- case TK_U: return "TK_U";
- case TK_V: return "TK_V";
- case TK_W: return "TK_W";
- case TK_X: return "TK_X";
- case TK_Y: return "TK_Y";
- case TK_Z: return "TK_Z";
- case TK_0: return "TK_0";
- case TK_1: return "TK_1";
- case TK_2: return "TK_2";
- case TK_3: return "TK_3";
- case TK_4: return "TK_4";
- case TK_5: return "TK_5";
- case TK_6: return "TK_6";
- case TK_7: return "TK_7";
- case TK_8: return "TK_8";
- case TK_9: return "TK_9";
- case TK_ID: return "TK_ID";
- case TK_NUM_LIT: return "TK_NUM_LIT";
- case TK_STR_LIT: return "TK_STR_LIT";
- default: return "TK_UNKNOWN";
- }
- return "TK_UNKNOWN";
- }
- struct tokenizer_options
- tokenizer_options_defaultlyzer(struct tokenizer_options *tkn_opts)
- {
- struct tokenizer_options defs = {0};
- if ( tkn_opts != NULL ) {
- defs = *tkn_opts;
- }
- LIB_SET_IF_NULL(defs.skip_token, tokenizer_skip_token);
- LIB_SET_IF_NULL(defs.is_id, tokenizer_is_id);
- LIB_SET_IF_NULL(defs.is_id_start, tokenizer_is_id_start);
- LIB_SET_IF_NULL(defs.is_digit, tokenizer_is_digit);
- LIB_SET_IF_NULL(defs.is_num_lit, tokenizer_is_num_lit);
- LIB_SET_IF_NULL(defs.is_str_lit_start, tokenizer_is_str_lit_start);
- LIB_SET_IF_NULL(defs.is_str_lit_end, tokenizer_is_str_lit_end);
- LIB_SET_IF_NULL(defs.is_str_lit, tokenizer_is_str_lit);
- LIB_SET_IF_NULL(defs.skip_token, tokenizer_skip_token);
- return defs;
- }
- bool
- tokenizer_skip_token(struct tokenizer *tkn, char c)
- {
- UNUSED(tkn);
- return (c == ' ') || (c == '\n') || (c == '\r') || (c == '\t');
- }
- bool
- tokenizer_is_id(struct tokenizer *tkn, char c)
- {
- UNUSED(tkn);
- return (c == '_') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
- }
- bool
- tokenizer_is_id_start(struct tokenizer *tkn, char c)
- {
- UNUSED(tkn);
- return tokenizer_is_id(tkn, c);
- }
- bool
- tokenizer_is_digit(struct tokenizer *tkn, char c)
- {
- UNUSED(tkn);
- return (c >= '0' && c <= '9');
- }
- bool
- tokenizer_is_num_lit(struct tokenizer *tkn, struct str str)
- {
- u64 i = 0;
- UNUSED(tkn);
- for ( i = 0; i < str.size; ++i ) {
- if ( ! tokenizer_is_digit(tkn, str.data[i]) ) {
- return false;
- }
- }
- return true;
- }
- bool
- tokenizer_is_str_lit_start(struct tokenizer *tkn, char c)
- {
- UNUSED(tkn);
- return (c == '\'' || c == '"');
- }
- bool
- tokenizer_is_str_lit_end(struct tokenizer *tkn, char c)
- {
- return tokenizer_is_str_lit_start(tkn, c);
- }
- bool
- tokenizer_is_str_lit(struct tokenizer *tkn, struct str str)
- {
- UNUSED(tkn);
- UNUSED(str);
- return true;
- }
- # endif /* defined(IMP) || defined(IMP_TOKENIZER) */
- # endif /* defined(WANT_TOKENIZER) || defined(WANT_ALL) */
- /* -------------------------- END TOKENIZER DEF ---------------------------- */
- /* ---------------------------- START CMD DEF ------------------------------ */
- # if defined(WANT_CMD) || defined(WANT_ALL)
- struct cmd {
- char *exe;
- struct {
- char **data;
- u64 size;
- u64 cap;
- } args;
- };
- # define cmd_create_ns(Exe, OutErr) \
- cmd_create( \
- (struct str) { \
- .data=(Exe), \
- .size=cstr_len_max((Exe), STR_SIZE_LIMIT, NULL, (OutErr)) \
- }, \
- (OutErr) \
- )
- struct cmd cmd_create(struct str exe, enum err *_r_ out_err);
- # define cmd_set_exe_ns(Cmd, Exe, OutErr) \
- cmd_set_exe( \
- (Cmd), \
- (struct str) { \
- .data=(Exe), \
- .size=cstr_len_max((Exe), STR_SIZE_LIMIT, NULL, (OutErr)) \
- }, \
- (OutErr) \
- )
- enum err cmd_set_exe(struct cmd *_r_ cmd, struct str exe,
- enum err *_r_ out_err);
- # define cmd_append_arg_ns(Cmd, Arg, OutErr) \
- cmd_append_arg( \
- (Cmd), \
- (struct str) { \
- .data=(Arg), \
- .size=cstr_len_max((Arg), STR_SIZE_LIMIT, NULL, (OutErr)) \
- }, \
- (OutErr) \
- )
- enum err cmd_append_arg(struct cmd *_r_ cmd, struct str arg,
- enum err *_r_ out_err);
- enum err cmd_exec(struct cmd *_r_ cmd, enum err *_r_ out_err);
- enum err cmd_destroy(struct cmd *cmd, enum err *out_err);
- # if defined(IMP_CMD) || defined(IMP)
- struct cmd
- cmd_create(struct str exe, enum err *_r_ out_err)
- {
- struct cmd empty = {0};
- struct cmd cmd = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- LIB_ARG_MUST_NOT_BE_NULL(exe.data, out_err, empty);
- cmd.exe = malloc(exe.size+1);
- if ( cmd.exe == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- goto exit_err;
- }
- cmd.exe[exe.size] = 0;
- memcpy(cmd.exe, exe.data, exe.size);
- cmd.args.cap = 32;
- cmd.args.data = malloc(sizeof(*cmd.args.data) * cmd.args.cap);
- if ( cmd.args.data == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- goto exit_err;
- }
- DA_APPEND(cmd.args, cmd.exe, out_err);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return cmd;
- exit_err:
- LIB_FREE(cmd.exe);
- LIB_FREE(cmd.args.data);
- return (struct cmd){0};
- }
- enum err
- cmd_set_exe(struct cmd *_r_ cmd, struct str exe, enum err *_r_ out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(exe.data, out_err);
- if ( cmd->exe != NULL ) {
- LIB_FREE(cmd->exe);
- }
- cmd->exe = malloc(exe.size+1);
- if ( cmd->exe == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- return ERR_FAILED_ALLOC;
- }
- cmd->exe[exe.size] = 0;
- memcpy(cmd->exe, exe.data, exe.size);
- cmd->args.data[0] = cmd->exe;
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- enum err
- cmd_append_arg(struct cmd *_r_ cmd, struct str arg, enum err *_r_ out_err)
- {
- enum err err = ERR_OK;
- enum err *perr = &err;
- char *t = NULL;
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->args.data, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(arg.data, out_err);
- if ( out_err != NULL ) {
- perr = out_err;
- }
- t = malloc(arg.size + 1);
- if ( t == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- return ERR_FAILED_ALLOC;
- }
- t[arg.size] = 0;
- memcpy(t, arg.data, arg.size);
- DA_APPEND(cmd->args, t, perr);
- return *perr;
- }
- enum err
- cmd_exec(struct cmd *_r_ cmd, enum err *_r_ out_err)
- {
- i32 pid = -1;
- i32 status = 0;
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->exe, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->args.data, out_err);
- cmd->args.data[cmd->args.size] = NULL;
- pid = fork();
- if ( pid < 0 ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_FORK);
- return ERR_FAILED_FORK;
- }
- if ( pid == 0 ) {
- /*
- printf("exe=`%s`\n", cmd->exe);
- DA_FOREACH(cmd->args, it) {
- printf("arg=`%s`\n", *it);
- }
- */
- execve(cmd->exe, cmd->args.data, NULL);
- exit(1);
- }
- if ( waitpid(pid, &status, 0) < 0 ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_WAITPID);
- return ERR_FAILED_WAITPID;
- }
- if ( WIFEXITED(status) == true ) {
- if ( WEXITSTATUS(status) != 0 ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_CMD_NON_ZERO_EXIT_CODE);
- return ERR_CMD_NON_ZERO_EXIT_CODE;
- }
- }
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- enum err
- cmd_destroy(struct cmd *cmd, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->exe, out_err);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(cmd->args.data, out_err);
- LIB_FREE(cmd->exe);
- DA_FOREACH(cmd->args, it) {
- if ( *it == cmd->exe ) continue;
- LIB_FREE(*it);
- }
- LIB_FREE(cmd->args.data);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- # endif /* defined(IMP_CMD) || defined(IMP) */
- # endif /* defined(WANT_CMD) || defined(WANT_ALL) */
- /* ----------------------------- END CMD DEF ------------------------------- */
- /* ---------------------------- START SGFX DEF ----------------------------- */
- # if defined(WANT_SGFX) || defined(WANT_ALL)
- # ifndef SGFX_WIDTH
- # define SGFX_WIDTH 800
- # endif /* SGFX_WIDTH */
- # ifndef SGFX_HEIGHT
- # define SGFX_HEIGHT 600
- # endif /* SGFX_HEIGHT */
- # define SGFX_WIDTH_CSTR MACRO_STR_VALUE_X(SGFX_WIDTH)
- # define SGFX_HEIGHT_CSTR MACRO_STR_VALUE_X(SGFX_HEIGHT)
- struct sgfx_rgb {
- u8 r, g, b;
- };
- struct sgfx_rgba {
- u8 r, g, b, a;
- };
- struct sgfx_canvas {
- u32 pixels[SGFX_WIDTH * SGFX_HEIGHT];
- u64 width;
- u64 height;
- u64 cap;
- };
- enum err sgfx_canvas_populate(struct sgfx_canvas *canvas, enum err *out_err);
- enum err sgfx_canvas_fill(struct sgfx_canvas *canvas, u32 color,
- enum err *out_err);
- enum err sgfx_canvas_fill_rect(struct sgfx_canvas *canvas,
- struct u64vec2 pos, struct u64vec2s size,
- u32 color,
- enum err *out_err);
- enum err sgfx_canvas_save_to_ppm(const struct sgfx_canvas *canvas,
- struct path path, enum err *out_err);
- # endif /* defined(WANT_SGFX) || defined(WANT_ALL) */
- /* ----------------------------- END SGFX DEF ------------------------------ */
- /* --------------------------- START RAYLIB DEF ---------------------------- */
- # if defined(WANT_RAYLIB) || defined(WANT_ALL)
- # if defined(RAYLIB_H)
- enum err raylib_draw_str(const struct str_builder *str, Font font,
- Vector2 position, float fontSize,
- float spacing, Color tint, enum err *out_err);
- # endif /* defined(RAYLIB_H) */
- # endif /* defined(WANT_RAYLIB) || defined(WANT_ALL) */
- /* ---------------------------- END RAYLIB DEF ----------------------------- */
- /* ---------------------------- START GUI DEF ------------------------------ */
- # if defined(WANT_GUI) || defined(WANT_ALL)
- enum gui_unit_type {
- GUT_ABSOLUTE = 0,
- GUT_PERCENTAGE
- };
- enum gui_unit_reference {
- GUR_TOP_LEFT = 0,
- GUR_CENTER
- };
- struct gui_unit {
- enum gui_unit_type type;
- enum gui_unit_reference ref;
- i64 value;
- };
- enum gui_item_type {
- GIT_BUTTOM = 0
- };
- struct gui_item {
- enum gui_item_type type;
- struct gui_unit x;
- struct gui_unit y;
- struct gui_unit width;
- struct gui_unit height;
- };
- struct gui {
- struct {
- struct gui_item *data;
- u64 size;
- u64 cap;
- } items;
- };
- struct gui gui_open_window(const char *title, enum err *out_err);
- bool gui_should_close(struct gui *gui, enum err *out_err);
- enum err gui_start_loop(struct gui *gui, enum err *out_err);
- enum err gui_add_buttom(struct gui *gui,
- struct gui_unit x, struct gui_unit y,
- struct gui_unit width, struct gui_unit height,
- enum err *out_err);
- enum err gui_end_loop(struct gui *gui, enum err *out_err);
- enum err gui_close_window(struct gui *gui, enum err *out_err);
- # if defined(IMP) || defined(IMP_STR)
- struct gui
- gui_open_window(const char *title, enum err *out_err)
- {
- struct gui empty = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- LIB_ARG_MUST_NOT_BE_NULL(title, out_err, empty);
- # if defined(RAYLIB_H)
- InitWindow(800, 600, title);
- SetWindowState(FLAG_WINDOW_RESIZABLE);
- # endif /* defined(RAYLIB_H) */
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return empty;
- }
- bool
- gui_should_close(struct gui *gui, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, true);
- LIB_ARG_MUST_NOT_BE_NULL(gui, out_err, true);
- (void) gui;
- # if defined(RAYLIB_H)
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return WindowShouldClose();
- # endif /* defined(RAYLIB_H) */
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return true;
- }
- enum err
- gui_start_loop(struct gui *gui, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(gui, out_err);
- # if defined(RAYLIB_H)
- BeginDrawing();
- # endif /* defined(RAYLIB_H) */
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- enum err
- gui_add_buttom(struct gui *gui,
- struct gui_unit x, struct gui_unit y,
- struct gui_unit width, struct gui_unit height,
- enum err *out_err)
- {
- # if defined(RAYLIB_H)
- Color red = { 230, 41, 55, 255 };
- # endif /* defined(RAYLIB_H) */
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(gui, out_err);
- # if defined(RAYLIB_H)
- DrawRectangle((i32)x.value, (i32)y.value,
- (i32)width.value, (i32)height.value, red);
- # endif /* defined(RAYLIB_H) */
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- enum err
- gui_end_loop(struct gui *gui, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(gui, out_err);
- # if defined(RAYLIB_H)
- EndDrawing();
- # endif /* defined(RAYLIB_H) */
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- enum err
- gui_close_window(struct gui *gui, enum err *out_err)
- {
- LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(gui, out_err);
- # if defined(RAYLIB_H)
- CloseWindow();
- # endif /* defined(RAYLIB_H) */
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- # endif /* defined(IMP) || defined(IMP_STR) */
- # endif /* defined(WANT_GUI) || defined(WANT_ALL) */
- /* ----------------------------- END GUI DEF ------------------------------- */
- /* ---------------------------- START SLOP DEF ----------------------------- */
- # if defined(WANT_SLOP) || defined(WANT_ALL)
- u8 *slop_file_slurp(const char *_r_ path, u64 *_r_ out_size,
- enum err *_r_ out_err);
- enum err slop_file_save(const char *_r_ path, u8 *_r_ data, u64 size,
- enum err *_r_ out_err);
- # if defined(IMP) || defined(IMP_SLOP)
- u8 *
- slop_file_slurp(const char *_r_ path, u64 *_r_ out_size, enum err *_r_ out_err)
- {
- enum err err = ERR_OK;
- enum err *perr = &err;
- struct path p = {0};
- struct file f = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
- LIB_ARG_MUST_NOT_BE_NULL(path, out_err, NULL);
- if ( out_err != NULL ) {
- perr = out_err;
- }
- p = path_from_cstr_ns(path, perr);
- f = path_file_read_all(&p, perr);
- if ( out_size != NULL ) {
- *out_size = f.size;
- }
- return f.data;
- }
- enum err slop_file_save(const char *_r_ path, u8 *_r_ data, u64 size,
- enum err *_r_ out_err);
- # endif /* defined(IMP) || defined(IMP_SLOP) */
- # endif /* defined(WANT_SLOP) || defined(WANT_ALL) */
- /* ----------------------------- END SLOP DEF ------------------------------ */
- # if defined(IMP) || defined(IMP_STR)
- # define _SET_IF_NOT_NULL(var, err) \
- if ( var != NULL ) { \
- *var = err; \
- }
- # define _ARG_IF_NOT_NULL_MUST_BE(arg, val, ret_val) \
- if ( arg != NULL ) { \
- if ( *arg != val ) { \
- return ret_val; \
- } \
- }
- # define _ARG_IF_NOT_NULL_MUST_BE_RET_IT(arg, val) \
- if ( arg != NULL ) { \
- if ( *arg != val ) { \
- return *arg; \
- } \
- }
- # define _ARG_MUST_NOT_BE_NULL_RET_ERR(arg) \
- if ( (arg) == NULL ) { \
- return ERR_NULL_ARG; \
- }
- # define _ARG_MUST_NOT_BE_NULL(arg, err_var, ret_val) \
- if ( (arg) == NULL ) { \
- _SET_IF_NOT_NULL(err_var, ERR_NULL_ARG); \
- return ret_val; \
- }
- # define _ARG_MUST_NOT_BE_NULL_SET_RET_ERR(arg, err_var) \
- if ( (arg) == NULL ) { \
- _SET_IF_NOT_NULL(err_var, ERR_NULL_ARG); \
- return ERR_NULL_ARG; \
- }
- # ifndef _CTYPE_H
- # define LIB_H_CTYPE
- # define isspace(c) ((c) == ' ' || (c) == '\f' \
- || (c) == '\n' || (c) == '\r' \
- || (c) == '\t' || (c) == '\v')
- # define isdigit(c) ((c) >= '0' && (c) <= '9')
- # endif /* _CTYPE_H */
- # ifndef _STRING_H
- # define LIB_H_STRING
- void *_str_memcpy(void *dest, const void *src, u64 n);
- void *
- _str_memcpy(void *dest, const void *src, u64 n)
- {
- u64 i = 0;
- char *_dest = (char *) dest;
- char *_src = (char *) src;
- for ( i = 0; i < n; ++i ) {
- _dest[i] = _src[i];
- }
- return dest;
- }
- # define memcpy _str_memcpy
- # endif /* _STRING_H */
- /* ----------------------------- START LIB IMP ----------------------------- */
- /* ------------------------------ END LIB IMP ------------------------------ */
- /* ---------------------------- START CSTR IMP ----------------------------- */
- # if defined(WANT_CSTR) || defined(WANT_ALL)
- u64
- cstr_len_max(const char *cstr, u64 max, bool *out_hit_max, enum err *out_err)
- {
- u64 ret = 0;
- _ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, 0);
- if ( cstr == NULL ) {
- _SET_IF_NOT_NULL(out_err, ERR_NULL_ARG);
- return 0;
- }
- _loop:
- if ( ret >= max ) {
- _SET_IF_NOT_NULL(out_hit_max, true);
- goto _loop_end;
- }
- if ( cstr[ret] == '\0' ) {
- goto _loop_end;
- }
- ++ret;
- goto _loop;
- _loop_end:
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return ret;
- }
- # endif /* defined(WANT_CSTR) || defined(WANT_ALL) */
- /* ----------------------------- END CSTR IMP ------------------------------ */
- /* ---------------------------- START STR DEF ------------------------------ */
- # if defined(WANT_STR) || defined(WANT_ALL)
- struct str
- str_from_cstr(const char *cstr, u64 cstr_size, enum err *out_err)
- {
- struct str empty = {0};
- struct str str = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- if ( cstr == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_NULL_ARG);
- return empty;
- }
- if ( cstr_size >= STR_SIZE_LIMIT ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_TOO_BIG);
- return empty;
- }
- str.data = cstr;
- str.size = cstr_size;
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return str;
- }
- struct str
- str_from_cstr_ns(const char *cstr, enum err *out_err)
- {
- struct str empty = {0};
- struct str str = {0};
- bool too_big = false;
- enum err err = ERR_OK;
- if ( cstr == NULL ) {
- _SET_IF_NOT_NULL(out_err, ERR_NULL_ARG);
- return empty;
- }
- str.size = cstr_len_max(cstr, STR_SIZE_LIMIT, &too_big, &err);
- if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return empty;
- }
- if ( too_big ) {
- _SET_IF_NOT_NULL(out_err, ERR_TOO_BIG);
- return empty;
- }
- str.data = cstr;
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return str;
- }
- struct str
- str_from_i64(i64 num, enum err *out_err)
- {
- struct str empty = {0};
- struct str str_temp = {0};
- struct str ret = {0};
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- str_temp = str_from_i64_temp(num);
- ret.size = str_temp.size;
- ret.should_be_freed = true;
- ret.data = malloc(str_temp.size);
- if ( ret.data == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- return empty;
- }
- memcpy((void *)ret.data, str_temp.data, str_temp.size);
- LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
- return ret;
- }
- struct str
- str_from_i64_temp(i64 num)
- {
- static char buffer[32];
- struct {
- char data[24];
- u8 size;
- } buf = {0};
- u64 _num = 0;
- struct str ret = {0};
- ret.data = buffer;
- if ( num < 0 ) {
- buf.data[buf.size++] = '-';
- num *= -1;
- }
- _num = (u64)num;
- while ( 1 ) {
- u8 mod = (u8) (_num % 10);
- buf.data[buf.size++] = (char) (mod + 48);
- _num /= 10;
- if ( buf.size >= 24 ) {
- _loop:
- buffer[ret.size++] = buf.data[--buf.size];
- if ( buf.size > 0 ) {
- goto _loop;
- }
- }
- if ( _num == 0 ) {
- break;
- }
- }
- if ( buf.size == 0 ) {
- goto exit;
- }
- _out_loop:
- buffer[ret.size++] = buf.data[--buf.size];
- if ( buf.size > 0 ) {
- goto _out_loop;
- }
- exit:
- buffer[ret.size] = 0;
- return ret;
- }
- struct str
- str_dup(struct str str)
- {
- struct str ret = str;
- ret.data = malloc(ret.size * sizeof(*ret.data));
- memcpy((char *)ret.data, str.data, str.size);
- ret.should_be_freed = true;
- return ret;
- }
- intmax_t
- str_to_int(struct str str, enum err *out_err)
- {
- intmax_t res = 0;
- u64 i = 0;
- bool negative = false;
- int digits[] = {
- 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000
- };
- if ( ! str_is_int(str) ) {
- _SET_IF_NOT_NULL(out_err, ERR_NOT_INT);
- return -1;
- }
- if ( str.size > STR_SIZE_LIMIT ) {
- _SET_IF_NOT_NULL(out_err, ERR_TOO_BIG);
- return -1;
- }
- negative = (str.data[0] == '-');
- if ( str.data[0] == '-' || str.data[0] == '+' ) {
- ++str.data;
- --str.size;
- }
- for ( i = 0; i < str.size; ++i ) {
- intmax_t digit = digits[(str.size - (i + 1))];
- res += (str.data[i] - 48) * digit;
- }
- if ( negative == true ) {
- res *= -1;
- }
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return res;
- }
- struct str
- str_rstrip(struct str str)
- {
- while ( isspace(str.data[str.size-1]) ) {
- --str.size;
- }
- return str;
- }
- struct str
- str_lstrip(struct str str)
- {
- while ( isspace(*str.data) ) {
- ++str.data;
- --str.size;
- }
- return str;
- }
- struct str
- str_strip(struct str str)
- {
- return str_lstrip(str_rstrip(str));
- }
- u64
- str_lindex(struct str str, char c)
- {
- u64 i = 0;
- for ( ; i < str.size; ++i ) {
- if ( str.data[i] == c ) {
- return i;
- }
- }
- return (u64) -1;
- }
- u64
- str_rindex(struct str str, char c)
- {
- u64 i = str.size - 1;
- for ( ; i > 0; --i ) {
- if ( str.data[i] == c ) {
- return i;
- }
- }
- if ( str.data[i] == c ) {
- return i;
- }
- return (u64) -1;
- }
- struct str_tokenizer
- str_tokenize(struct str str, char c)
- {
- struct str_tokenizer st = {0};
- st.str = str;
- st.c = c;
- return st;
- }
- struct str_tokenizer
- str_tokenize_func(struct str str, bool (*f)(char c))
- {
- struct str_tokenizer st = {0};
- st.str = str;
- st.f = f;
- return st;
- }
- struct str
- str_tokenizer_next(struct str_tokenizer *st)
- {
- struct str str;
- if ( st == NULL ) {
- goto ret_err;
- }
- if ( st->cur >= st->str.size ) {
- goto ret_done;
- }
- if ( st->str.data[st->cur] == '\0' ) {
- goto ret_done;
- }
- str = st->str;
- str.data += st->cur;
- str.size = 0;
- if ( st->f != NULL ) {
- while ( (! st->f(str.data[str.size]))
- && st->cur < st->str.size ) {
- ++str.size;
- ++st->cur;
- }
- } else {
- while ( str.data[str.size] != st->c
- && st->cur < st->str.size ) {
- ++str.size;
- ++st->cur;
- }
- }
- ++st->cur;
- if ( str.size == 0 ) {
- goto ret_empty;
- }
- return str;
- ret_empty:
- str.data = "";
- str.size = 0;
- return str;
- ret_done:
- str.data = "";
- str.size = (u64) -1;
- return str;
- ret_err:
- str.data = "";
- str.size = (u64) -2;
- return str;
- }
- struct str
- str_slice(struct str str, u64 from, u64 to)
- {
- if ( from > str.size ) {
- goto ret_err;
- }
- if ( from > to ) {
- goto ret_err;
- }
- to = ( to > str.size ) * str.size \
- + ( to <= str.size ) * to;
-
- str.data += from;
- str.size = to - from;
- return str;
- ret_err:
- str.data = "";
- str.size = (u64) -2;
- return str;
- }
- bool
- str_eq_cstr(struct str str, const char *cstr, u64 cstr_size)
- {
- u64 i = 0;
- if ( str.size != cstr_size ) {
- return false;
- }
- for ( i = 0; i < str.size; ++i ) {
- if ( str.data[i] != cstr[i] ) {
- return false;
- }
- }
- return true;
- }
- bool
- str_eq_str(struct str str1, struct str str2)
- {
- u64 i = 0;
- if ( str1.size != str2.size ) {
- return false;
- }
- for ( i = 0; i < str1.size; ++i ) {
- if ( str1.data[i] != str2.data[i] ) {
- return false;
- }
- }
- return true;
- }
- bool
- str_startswith_cstr(struct str str, const char *cstr, u64 cstr_size)
- {
- u64 i = 0;
- if ( cstr_size > str.size ) {
- return false;
- }
- for ( i = 0; i < cstr_size; ++i ) {
- if ( str.data[i] != cstr[i] ) {
- return false;
- }
- }
- return true;
- }
- bool
- str_is_int(struct str str)
- {
- u64 i = 0;
- if ( str.size == 0 ) {
- return false;
- }
- if ( str.size == 1 ) {
- return isdigit(str.data[0]);
- }
- i += (str.data[0] == '-' || str.data[0] == '+');
- for ( ; i < str.size; ++i ) {
- if ( ! isdigit(str.data[i]) ) {
- return false;
- }
- }
- return true;
- }
- struct str
- str_builder_to_str(const struct str_builder *str_bldr)
- {
- struct str str = {0};
- str.data = str_bldr->data;
- str.size = str_bldr->size;
- str.should_be_freed = true;
- return str;
- }
- # endif /* defined(WANT_STR) || defined(WANT_ALL) */
- /* ----------------------------- END STR IMP ------------------------------- */
- /* ---------------------------- START ENV IMP ------------------------------ */
- # if defined(WANT_ENV) || defined(WANT_ALL)
- struct str
- getenv_as_str(const char *name, enum err *out_err)
- {
- struct str empty = {0};
- struct str str = {0};
- char *res = NULL;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- LIB_ARG_MUST_NOT_BE_NULL(name, out_err, empty);
- res = getenv(name);
- if ( res == NULL ) {
- LIB_SET_IF_NOT_NULL(out_err, ERR_NOT_FOUND);
- return str;
- }
- return str_from_cstr_ns(res, out_err);
- }
- struct path
- getenv_as_path(const char *name, enum err *out_err)
- {
- struct path empty = {0};
- struct str str = {0};
- enum err err;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- LIB_ARG_MUST_NOT_BE_NULL(name, out_err, empty);
- str = getenv_as_str(name, &err);
- if ( err ) {
- LIB_SET_IF_NOT_NULL(out_err, err);
- return empty;
- }
- return path_from_str(str, out_err);
- }
- # endif /* defined(WANT_ENV) || defined(WANT_ALL) */
- /* ----------------------------- END ENV IMP ------------------------------- */
- /* ---------------------------- START PATH IMP ----------------------------- */
- # if defined(WANT_PATH) || defined(WANT_ALL)
- struct path
- path_from_str(struct str str, enum err *out_err)
- {
- struct path path = {0};
- if ( str.size > PATH_SIZE_LIMIT ) {
- _SET_IF_NOT_NULL(out_err, ERR_TOO_BIG);
- return path;
- }
- memcpy(path.data, str.data, str.size);
- path.size = str.size;
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return path;
- }
- struct path
- path_from_cstr(const char *cstr, u64 cstr_size, enum err *out_err)
- {
- enum err err;
- struct str str;
- struct path path = {0};
- str = str_from_cstr(cstr, cstr_size, &err);
- if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return path;
- }
- return path_from_str(str, out_err);
- }
- struct path
- path_from_cstr_ns(const char *cstr, enum err *out_err)
- {
- enum err err;
- struct str str;
- struct path path = {0};
- _ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, path);
- str = str_from_cstr_ns(cstr, &err);
- if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return path;
- }
- return path_from_str(str, out_err);
- }
- struct path
- path_get_xdg_state_home(enum err *out_err)
- {
- struct path empty = {0};
- struct path path = {0};
- enum err err;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- path = getenv_as_path("XDG_STATE_HOME", &err);
- if ( err == ERR_NOT_FOUND ) {
- path = getenv_as_path("HOME", &err);
- if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return empty;
- }
- path = path_join_with_cstr(path, ".local/state", 12, NULL);
- } else if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return empty;
- }
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return path;
- }
- struct path
- path_get_xdg_data_home(enum err *out_err)
- {
- struct path empty = {0};
- struct path path = {0};
- enum err err;
- LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- path = getenv_as_path("XDG_DATA_HOME", &err);
- if ( err == ERR_NOT_FOUND ) {
- path = getenv_as_path("HOME", &err);
- if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return empty;
- }
- path = path_join_with_cstr(path, ".local/share", 12, NULL);
- } else if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return empty;
- }
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return path;
- }
- struct path
- path_dirname(struct path path, enum err *out_err)
- {
- struct path empty = {0};
- struct path ret = {0};
- u64 i = 0;
- if ( path.size == 0 || path.data[0] == 0 ) {
- _SET_IF_NOT_NULL(out_err, ERR_PATH_EMPTY);
- return empty;
- }
- i = path.size;
- loop:
- --i;
- if ( path.data[i] == '/' ) {
- goto exit_loop;
- }
- if ( i == 0 ) {
- ret.data[0] = '.';
- ret.data[1] = 0;
- ret.size = 1;
- goto ret_ok;
- }
- goto loop;
- exit_loop:
- memcpy(ret.data, path.data, i);
- ret.size = i;
- ret_ok:
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return ret;
- }
- struct path
- path_join(struct path lhs, struct path rhs, enum err *out_err)
- {
- struct path path = {0};
- if ( (lhs.size + rhs.size + 1) > PATH_SIZE_LIMIT ) {
- _SET_IF_NOT_NULL(out_err, ERR_TOO_BIG);
- return path;
- }
- /* TODO: Check if lhs or rhs have / at the end and start respectively */
- path.size = (lhs.size + rhs.size + 1);
- memcpy(path.data, lhs.data, lhs.size);
- path.data[lhs.size] = '/';
- memcpy(path.data + lhs.size + 1, rhs.data, rhs.size);
- return path;
- }
- struct path
- path_join_with_str(struct path lhs, struct str rhs, enum err *out_err)
- {
- struct path path = {0};
- enum err err;
- path = path_from_str(rhs, &err);
- if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return path;
- }
- return path_join(lhs, path, out_err);
- }
- struct path
- path_join_with_cstr(struct path lhs, const char *rhs, u64 rhs_size,
- enum err *out_err)
- {
- struct path path = {0};
- enum err err;
- path = path_from_cstr(rhs, rhs_size, &err);
- if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return path;
- }
- return path_join(lhs, path, out_err);
- }
- struct path
- path_join_with_cstr_ns(struct path lhs, const char *rhs, enum err *out_err)
- {
- struct path empty = {0};
- struct path path = {0};
- enum err err;
- _ARG_MUST_NOT_BE_NULL(rhs, out_err, empty);
- path = path_from_cstr_ns(rhs, &err);
- if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return empty;
- }
- return path_join(lhs, path, out_err);
- }
- bool
- path_exists(struct path path, int (*access)(const char *, int))
- {
- return access(path.data, F_OK) == 0;
- }
- bool
- path_can_read(struct path path, int (*access)(const char *, int))
- {
- return access(path.data, R_OK) == 0;
- }
- bool
- path_can_write(struct path path, int (*access)(const char *, int))
- {
- return access(path.data, W_OK) == 0;
- }
- bool
- path_can_execute(struct path path, int (*access)(const char *, int))
- {
- return access(path.data, X_OK) == 0;
- }
- bool
- path_mkdir(struct path path, u32 mode, bool do_create_parents,
- int (*mkdir)(const char *, u32), enum err *out_err)
- {
- u64 i = 0;
- _ARG_MUST_NOT_BE_NULL(mkdir, out_err, false);
- if ( path.size == 1 ) {
- _SET_IF_NOT_NULL(out_err, ERR_PATH_INVALID);
- return 1;
- }
- if ( do_create_parents ) {
- for ( i = 1; i < path.size; ++i ) {
- if ( path.data[i] == '/' ) {
- path.data[i] = 0;
- mkdir(path.data, mode);
- path.data[i] = '/';
- }
- }
- }
- if ( ! mkdir(path.data, mode) ) {
- _SET_IF_NOT_NULL(out_err, ERR_MKDIR_FAILED);
- return false;
- }
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return true;
- }
- /*
- bool
- path_touch(struct path path, int (*open)(const char *, int), enum err *out_err)
- {
- int fd = -1;
- _ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, false);
- _ARG_MUST_NOT_BE_NULL(open, out_err, false);
- fd = open(path.data, 0100 | 00644);
- if ( fd == -1 ) {
- _SET_IF_NOT_NULL(out_err, ERR_PATH_FAILED_OPEN);
- return false;
- }
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return true;
- }
- */
- /* TODO: Replace this */
- #include <fcntl.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/stat.h>
- struct file
- path_file_read_all(const struct path *path, enum err *out_err)
- {
- struct file empty = {0};
- struct file file = {0};
- i64 file_size = -1;
- i32 fd = -1;
- _ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
- _ARG_MUST_NOT_BE_NULL(path, out_err, empty);
- fd = open(path->data, O_RDONLY);
- if ( fd < 0 ) {
- _SET_IF_NOT_NULL(out_err, ERR_FAILED_OPEN);
- goto exit_err;
- }
- file_size = lseek(fd, 0, SEEK_END);
- if ( file_size < 0 ) {
- _SET_IF_NOT_NULL(out_err, ERR_PATH_FILE_FAILED_SEEK);
- goto exit_err;
- }
- lseek(fd, 0, SEEK_SET);
- file.size = (u64) file_size;
- if ( file.size == 0 ) {
- _SET_IF_NOT_NULL(out_err, ERR_PATH_FILE_EMPTY);
- goto exit_err;
- }
- file.data = calloc(file.size + 1, sizeof(u8));
- if ( file.data == NULL ) {
- _SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
- goto exit_err;
- }
- {
- i64 rd = read(fd, file.data, file.size);
- if ( rd < 0 ) {
- _SET_IF_NOT_NULL(out_err, ERR_FAILED_READ);
- goto exit_err;
- }
- if ( rd == 0 ) {
- _SET_IF_NOT_NULL(out_err, ERR_PATH_FILE_EMPTY);
- goto exit_err;
- }
- }
- if ( close(fd) != 0 ) {
- /* It should be possible to handle EIO */
- _SET_IF_NOT_NULL(out_err, ERR_FAILED_CLOSE);
- return empty;
- }
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return file;
- exit_err:
- if ( file.data != NULL ) {
- free(file.data);
- }
- if ( fd > 0 ) {
- if ( close(fd) != 0 ) {
- /* It should be possible to handle EIO */
- _SET_IF_NOT_NULL(out_err, ERR_FAILED_CLOSE);
- return empty;
- }
- }
- return empty;
- }
- enum err
- path_file_save(const struct path *path, const struct file *file,
- enum err *out_err)
- {
- enum err err = ERR_OK;
- i64 wrote = -1;
- i32 fd = -1;
- _ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- _ARG_MUST_NOT_BE_NULL_SET_RET_ERR(path, out_err);
- _ARG_MUST_NOT_BE_NULL_SET_RET_ERR(file, out_err);
- fd = open(path->data, O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
- if ( fd < 0 ) {
- err = ERR_FAILED_OPEN;
- goto exit;
- }
- wrote = write(fd, file->data, file->size);
- if ( wrote == -1 ) {
- err = ERR_FAILED_WRITE;
- goto exit;
- }
- if ( ((u64) wrote) != file->size ) {
- err = ERR_WROTE_WRONG_AMOUNT;
- goto exit;
- }
- err = ERR_OK;
- exit:
- if ( close(fd) != 0 ) {
- /* It should be possible to handle EIO */
- err = ERR_FAILED_CLOSE;
- goto exit;
- }
- _SET_IF_NOT_NULL(out_err, err);
- return err;
- }
- # endif /* defined(WANT_PATH) || defined(WANT_ALL) */
- /* ----------------------------- END PATH IMP ------------------------------ */
- /* ---------------------------- START SGFX IMP ----------------------------- */
- # if defined(WANT_SGFX) || defined(WANT_ALL)
- enum err
- sgfx_canvas_populate(struct sgfx_canvas *canvas, enum err *out_err)
- {
- _ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- _ARG_MUST_NOT_BE_NULL_SET_RET_ERR(canvas, out_err);
- canvas->width = SGFX_WIDTH;
- canvas->height = SGFX_HEIGHT;
- canvas->cap = SGFX_WIDTH * SGFX_HEIGHT;
- _SET_IF_NOT_NULL(out_err, ERR_OK)
- return ERR_OK;
- }
- enum err
- sgfx_canvas_fill(struct sgfx_canvas *canvas, u32 color, enum err *out_err)
- {
- u64 i = 0;
- _ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- _ARG_MUST_NOT_BE_NULL_SET_RET_ERR(canvas, out_err);
- for ( i = 0; i < canvas->cap; ++i ) {
- canvas->pixels[i] = color;
- }
- _SET_IF_NOT_NULL(out_err, ERR_OK)
- return ERR_OK;
- }
- enum err
- sgfx_canvas_fill_rect(struct sgfx_canvas *canvas,
- struct u64vec2 pos, struct u64vec2s size, u32 color,
- enum err *out_err)
- {
- u64 i = 0;
- u64 j = 0;
- u64 startp = 0;
- u64 endp = 0;
- _ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- _ARG_MUST_NOT_BE_NULL_SET_RET_ERR(canvas, out_err);
- /* TODO: Create a diferent error for when size lands outside canvas */
- if ( pos.x > canvas->width || pos.y > canvas->height
- || (pos.x + size.w) > canvas->width
- || (pos.y + size.h) > canvas->height ) {
- _SET_IF_NOT_NULL(out_err, ERR_SGFX_POS_OUTSIDE_CANVAS);
- return ERR_SGFX_POS_OUTSIDE_CANVAS;
- }
- /*
- printf("pos.x -> %ld || pos.y -> %ld\n", pos.x, pos.y);
- printf("size.w -> %ld || size.h -> %ld\n", size.w, size.h);
- printf("(pos.x + size.w) -> %ld || (pos.y + size.h) -> %ld\n", (pos.x + size.w), (pos.y + size.h));
- */
- startp = (canvas->width * pos.y) + pos.x;
- endp = (canvas->width * (pos.y + size.h)) + (pos.x + size.w);
- if ( endp >= canvas->cap ) {
- endp = canvas->cap;
- }
- for ( i = startp; i < endp; i += canvas->width ) {
- for ( j = i; j < i+size.w; ++j ) {
- canvas->pixels[j] = color;
- }
- }
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- }
- enum err
- sgfx_canvas_save_to_ppm(const struct sgfx_canvas *canvas, struct path path,
- enum err *out_err)
- {
- #define __T(s) s, cstr_len_max(s, 255, NULL, out_err)
- /* enum err err = ERR_OK; */
- /* u64 i = 0; */
- /* i32 fd = -1; */
- (void) path;
- _ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- _ARG_MUST_NOT_BE_NULL_SET_RET_ERR(canvas, out_err);
- /* TODO: Check the errors */
- /*
- fd = open(path.data, O_RDWR | O_CREAT, 00644);
- if ( err ) {
- _SET_IF_NOT_NULL(out_err, err);
- return err;
- }
- write(fd, __T("P6\n"));
- write(fd, __T(SGFX_WIDTH_CSTR"\n"));
- write(fd, __T(SGFX_HEIGHT_CSTR"\n"));
- write(fd, __T("255\n"));
- for ( i = 0; i < canvas->cap; ++i ) {
- struct sgfx_rgb rgb = {0};
- rgb.r = (u8)(canvas->pixels[i] >> 24);
- rgb.g = (u8)(canvas->pixels[i] >> 16);
- rgb.b = (u8)(canvas->pixels[i] >> 8);
- write(fd, &rgb, sizeof(struct sgfx_rgb));
- }
- close(fd);
- */
- _SET_IF_NOT_NULL(out_err, ERR_OK);
- return ERR_OK;
- #undef __T
- }
- # endif /* defined(WANT_SGFX) || defined(WANT_ALL) */
- /* ----------------------------- END SGFX IMP ------------------------------ */
- /* --------------------------- START RAYLIB IMP ---------------------------- */
- # if defined(WANT_RAYLIB) || defined(WANT_ALL)
- # if defined(RAYLIB_H)
- enum err
- raylib_draw_str(const struct str_builder *str, Font font, Vector2 position,
- float fontSize, float spacing, Color tint, enum err *out_err)
- {
- enum err err = ERR_OK;
- char *cstr = NULL;
- _ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
- cstr = calloc(str->size + 1, sizeof(char));
- if ( cstr == NULL ) {
- err = ERR_FAILED_ALLOC;
- goto exit;
- }
- memcpy(cstr, str->data, str->size);
- DrawTextEx(font, cstr, position, fontSize, spacing, tint);
- err = ERR_OK;
- exit:
- if ( cstr != NULL ) {
- free(cstr);
- }
- _SET_IF_NOT_NULL(out_err, err);
- return err;
- }
- # endif /* defined(RAYLIB_H) */
- # endif /* defined(WANT_RAYLIB) || defined(WANT_ALL) */
- /* ---------------------------- END RAYLIB IMP ----------------------------- */
- # ifdef LIB_H_CTYPE
- # undef LIB_H_CTYPE
- # undef isspace
- # undef isdigit
- # endif /* LIB_H_CTYPE */
- # ifdef LIB_H_STRING
- # undef LIB_H_STRING
- # undef memcpy
- # endif /* LIB_H_STRING */
- # undef _SET_IF_NOT_NULL
- # undef _ARG_IF_NOT_NULL_MUST_BE
- # undef _ARG_MUST_NOT_BE_NULL
- # endif /* defined(IMP) || defined(IMP_STR) */
- # ifdef LIB_H_ALLOC_FUNC
- # undef LIB_H_ALLOC_FUNC
- # undef ALLOC_FUNC
- # endif /* LIB_H_ALLOC_FUNC */
- # ifdef LIB_H_STDBOOL
- # undef LIB_H_STDBOOL
- # undef bool
- # undef true
- # undef false
- # endif /* LIB_H_STDBOOL */
- # ifdef LIB_H_NULL
- # undef LIB_H_NULL
- # undef NULL
- # endif /* LIB_H_NULL */
- # ifdef LIB_H_UNISTD
- # undef LIB_H_UNISTD
- # undef R_OK
- # undef W_OK
- # undef X_OK
- # undef F_OK
- # endif /* LIB_H_UNISTD */
- # ifdef LIB_H_STDINT
- # undef LIB_H_STDINT
- # undef intmax_t
- # endif /* LIB_H_STDINT */
- #endif /* LIB_H */
|