#ifndef INCGUARD_aM91R0ljMWoqtn7F #define INCGUARD_aM91R0ljMWoqtn7F #if 0 Qntan - A C module separations framework http://git.hiddenalpha.ch/qntan.git/tree/README.txt Doc comments for structs FOLLOW the top of the structs body. Doc comments for members FOLLOW its signature declaration. Eg: struct Foo { /* Doc for 'Foo' goes here. */ int (*myFunc)( int x ); /* Here goes description of 'myFunc'. */ }; #endif #include /* size_t */ #include /* uintptr_t */ #if __cplusplus extern "C" { #endif /* * "Cls" aka "Closure". The userdata type to pass around for callbacks etc. */ #define Qntan_Cls uintptr_t #define QNTAN_CLS(OBJ) ((Qntan_Cls)OBJ) /* data fwd decls */ struct Qntan_EvLoop; struct Qntan_Mallocator; struct Qntan_MemArena; struct Qntan_Executor; struct Qntan_Scheduler; struct Qntan_IoMux; struct Qntan_File; struct Qntan_FileSystem; struct Qntan_FourierTransform; struct Qntan_Process; struct Qntan_HshTbl; struct Qntan_HshTbl_Cursor; struct Qntan_Socket; struct Qntan_TarEnc; struct Qntan_TarEnc_Hdr; struct Qntan_TarDec; struct Qntan_TarDec_Hdr; struct Qntan_Cond; struct Qntan_Mutx; struct Qntan_Networker; struct Qntan_CsvDec; struct Qntan_CsvDec_Mentor; struct Qntan_CsvIStream; struct Qntan_CsvIStream_Mentor; struct Qntan_JsonEnc; struct Qntan_JsonDec; struct Qntan_JsonDec_Mentor; struct Qntan_JsonTreeDec; struct Qntan_JsonTreeDec_JsonNode; struct Qntan_XmlDec; struct Qntan_XmlDec_Mentor; struct Qntan_HttpClient; struct Qntan_HttpClient_Exchg; struct Qntan_HttpClient_Exchg_Opts; struct Qntan_GfxRenderer; struct Qntan_JavaBytecodeParser; struct Qntan_JavaBytecodeParser_Mentor; struct Qntan_CamtAccount; struct Qntan_CamtTransaction; struct Qntan_CamtDec; struct Qntan_CamtDec_Mentor; #ifndef Qntan_EvLoop_enque # define Qntan_EvLoop_enque(A, B, C) (*A)->enque(A, B, C) #endif #ifndef Qntan_EvLoop_awaitTokenAdd # define Qntan_EvLoop_awaitTokenAdd(A) (*A)->addAwaitToken(A) #endif #ifndef Qntan_EvLoop_awaitTokenDel # define Qntan_EvLoop_awaitTokenDel(A) (*A)->delAwaitToken(A) #endif #ifndef Qntan_EvLoop_runUntilPause # define Qntan_EvLoop_runUntilPause(A) (*A)->runUntilPause(A) #endif #ifndef Qntan_EvLoop_runUntilDone # define Qntan_EvLoop_runUntilDone(A) (*A)->runUntilDone(A) #endif #ifndef Qntan_EvLoop_isEvLoopThread # define Qntan_EvLoop_isEvLoopThread(A) (*A)->isEvLoopThread(A) #endif struct Qntan_EvLoop { void (*enque)( struct Qntan_EvLoop**, void(*fn)(Qntan_Cls), Qntan_Cls ); /* enque a task to the EvLoop. See also Qntan_ThreadPool.enque(). */ void (*addAwaitToken)( struct Qntan_EvLoop** ); /* TODO write doc */ void (*delAwaitToken)( struct Qntan_EvLoop** ); /* TODO write doc */ int (*runUntilPause)( struct Qntan_EvLoop** ); /* Process reactor tasks until task queue gets drained. * TODO document return value */ void (*runUntilDone)( struct Qntan_EvLoop** ); /* Process reactor tasks until event loop is signalized to end. */ int (*isEvLoopThread)( struct Qntan_EvLoop** ); /* returns NON-zero, if called from the EvLoopThread. This is intended for * assertions, to check that one is running on the expected thread. */ }; #ifndef Qntan_Mallocator_realloc # define Qntan_Mallocator_realloc(A, B, C, D) (*A)->realloc(A, B, C, D) #endif struct Qntan_Mallocator { /**/ void* (*realloc)( struct Qntan_Mallocator**, void*oldPtr, size_t oldPtr_sz, size_t newPtr_sz ); /* Basic idea is * "https://pubs.opengroup.org/onlinepubs/9699919799/functions/realloc.html". * But keep these details in mind: * * Errors are reported via 'errno' as defined by 'realloc' and related * functions. * * In contrast to the traditional funcs, this API requires to also * pass in the size of 'oldPtr'. If you disagree with this decision you * should read "https://nullprogram.com/blog/2023/12/17/". * * Example "allocate space for an object": * struct Foo *foo = (*m)->realloc(m, NULL, 0, sizeof*foo) * if( !foo ){ handle errno... } * * Example "free foo": * (*m)->realloc(m, foo, sizeof*foo, 0) * * Example "enlarge foo from 42 to 1042": * void*tmp = (*m)->realloc(m, foo, 42, 1042) * if( !tmp ){ handle errno... } * foo = tmp; */ }; struct Qntan_MemArena { /* Let's say, a special kind of mallocator. Traditionally on a mallocator, caller * is responsible to ensure alloc/free pairs of calls to prevent memory leaks. * On an arena in contrast, individual 'free' for every alloc is NOT needed, as * all the allocated space will be free'd at the end of the arenas lifetime. * Nevertheless, freeing blocks is still ok. Free calls MUST be transparent to * the caller and behave like the one in a mallocator. But the arena CAN decide * itself if it will free anything, or it just ignore the 'free' request (as it * is going to free everything soon anyway for example). */ void* (*realloc)( struct Qntan_MemArena**, void*oldPtr, size_t oldPtr_sz, size_t newPtr_sz ); /* See 'Qntan_Mallocator.realloc()'. */ }; struct Qntan_Executor { /**/ void (*enque)( struct Qntan_Executor**, void(*fn)(Qntan_Cls), Qntan_Cls ); /* enque a task to this executor. How the task gets executed depends on what * executor instance got chosen. This also includes stuff like ThreadPools * which may execute stuff out of order. */ }; struct Qntan_Scheduler { /**/ void (*onceAfterMs)( struct Qntan_Scheduler**, int delayMs, void(*fn)(Qntan_Cls), Qntan_Cls ); /* Schedule 'fn' to be called after 'delayMs' milliseconds. * TODO: Specify if time refers to wall-clock, monotonic, etc. For now this * behavior is implementation-defined, BUT MAY IT WILL BE SPECIFIED HERE IN * FUTURE! */ }; struct Qntan_IoMux { /* An IO Multiplexer. * * WARN: This is considered a low-level module! It SHOULD only be used by * low-level modules which abstract away the details of the effective * file/socket types in use. High-level modules SHOULD NOT use this type * directly. */ void (*read)( struct Qntan_IoMux**, void*buf, int sz, int cnt, uintptr_t ptrToFILE, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* Basic idea is from * "https://pubs.opengroup.org/onlinepubs/009695399/functions/fread.html". * BUT be aware that there are some differences mentioned here! * * WARN: 'sz' times 'cnt' outside range 0..INT_MAX is UNDEFINED BEHAVIOR! It * is recommended that an implementation fails hard if this happens. For * example by calling 'abort()'. * * @param ptrToFILE * Is a `FILE*` (NOT FileDescriptor!). In most cases you'll need a * cast to uintptr_t. * @param onDone * Called as soon operation has completed. * @param ret * Negative numbers indicate errors. Zero indicates EOF. Positive * values indicate number of objects that where read. */ void (*write)( struct Qntan_IoMux**, void const*buf, int sz, int cnt, uintptr_t ptrToFILE, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* Basic idea is from * "https://pubs.opengroup.org/onlinepubs/009695399/functions/fwrite.html". * BUT be aware that there are some differences mentioned here! * * WARN: 'sz' times 'cnt' outside range 0..INT_MAX is UNDEFINED BEHAVIOR! It * is recommended that an implementation fails hard if this happens. For * example by calling 'abort()'. * * @param ptrToFILE * Is a `FILE*` (NOT FileDescriptor!). In most cases you'll need a * cast to uintptr_t. * @param onDone * Called as soon operation has completed. * @param ret * Negative numbers indicate errors. Positive values indicate * number of objects written. * TODO define what zero means. * @param arg * User defined pointer to pass a context to 'onDone'. */ void (*flush)( struct Qntan_IoMux**, uintptr_t ptrToFILE, void(*onDone)(int,Qntan_Cls), Qntan_Cls ); /* @param ptrToFILE * Is a `FILE*` (NOT FileDescriptor!). In most cases you'll need a * cast to uintptr_t. */ void (*send)( struct Qntan_IoMux**, uintptr_t fd, void const*buf, int len, int flags, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* Basic idea is from * "https://pubs.opengroup.org/onlinepubs/000095399/functions/send.html". * BUT be aware that there are some differences mentioned here! * Calls to send MUST NOT overlap. So as long a send call is in progress, * send MUST NOT be called meanwhile. * * @param fd * FileDescriptor (NOT 'FILE*'!). (Or 'HANDLE' on some ugly platforms). * @param onDone * Called as soon operation has completed. * @param ret * Negative numbers indicate errors. Positive values indicate * number of objects that where read. * @param arg * User defined pointer to pass a context to 'onDone'. */ void (*recv)( struct Qntan_IoMux**, uintptr_t fd, void*buf, int len, int flags, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* Basic idea is from * "https://pubs.opengroup.org/onlinepubs/009695399/functions/recv.html". * BUT be aware that there are some differences mentioned here! * Calls to recv MUST NOT overlap. So as long a recv call is in progress, * recv MUST NOT be called meanwhile. * * @param fd * FileDescriptor (NOT 'FILE*'!). (Or 'HANDLE' on some ugly platforms). * @param onDone * Called as soon operation has completed. * @param ret * Negative numbers indicate errors. Zero indicates EOF. Positive * values indicate number of objects that where read. * @param arg * User defined pointer to pass a context to 'onDone'. */ void (*accept)( struct Qntan_IoMux**, uintptr_t sockFd, int flgs, void(*onDone)(int ret, uintptr_t newClientFd, void*sockaddr, int sockaddr_len, Qntan_Cls), Qntan_Cls ); /* Basic idea is from * "https://pubs.opengroup.org/onlinepubs/009695399/functions/accept.html". * Just with a slightly different API. * * @param sockFd * FileDescriptor (NOT 'FILE*'!). Or 'HANDLE' on some ugly platforms. * @param flgs * Set 0x1 if you want 'sockaddr' to be filled. * Setting any other bit is UNDEFINED BEHAVIOR! * @param newClientFd * FileDescriptor (NOT 'FILE*'!). Or 'HANDLE' on some ugly platforms. * The newly accepted client. * @param sockaddr, sockaddr_len * Address of the new client. WARN: Only valid if it got * requested via 'flgs'. This is only valid as long 'onDone' * has not yet returned. */ }; struct Qntan_File { /**/ void (*flush)( struct Qntan_File**, void(*onDone)(int ret, Qntan_Cls), Qntan_Cls ); /**/ void (*write)( struct Qntan_File**, void const*buf, int sz, int cnt, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* Basic idea is from * "https://pubs.opengroup.org/onlinepubs/000095399/functions/write.html". * BUT be aware that there are some differences mentioned here! * Calls to write MUST NOT overlap. So as long a write call is in progress, * write MUST NOT be called meanwhile. * * @param onDone * Called as soon operation has completed. * @param ret * Negative numbers indicate errors. Positive values indicate * number of objects that where read. */ void (*read)( struct Qntan_File**, void*buf, int sz, int cnt, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* Basic idea is from * "https://pubs.opengroup.org/onlinepubs/009695399/functions/recv.html". * BUT be aware that there are some differences mentioned here! * Calls to recv MUST NOT overlap. So as long a recv call is in progress, * recv MUST NOT be called meanwhile. * * @param onDone * Called as soon operation has completed. * @param ret * Negative numbers indicate errors. Zero indicates EOF. Positive * values indicate number of objects that where read. */ void (*seek)( struct Qntan_File**, int64_t off, int whence, void(*onDone)(int ret, Qntan_Cls), Qntan_Cls ); /* "https://pubs.opengroup.org/onlinepubs/007904875/functions/fseek.html" * TODO: Maybe this func should be without cback? */ void (*tell)( struct Qntan_File**, void(*onDone)(int64_t ret, Qntan_Cls), Qntan_Cls ); /* "https://pubs.opengroup.org/onlinepubs/007904875/functions/ftell.html" * TODO: Maybe this func should be without cback? */ void (*truncate)( struct Qntan_File**, int64_t size, void(*onDone)(int,Qntan_Cls), Qntan_Cls ); /* TODO doc * TODO There's a duplicate in 'FileSystem' of this function. * WARN: size MUST be zero. Any other value is UB! (aka reserved for * future specifications) */ }; #ifndef Qntan_Executor_enque # define Qntan_Executor_enque(A, ...) (*A)->enque(A, __VA_ARGS__) #endif struct Qntan_FileSystem { /* VFS (VirtualFileSystem) * WARN: Heavily experimental API! * TODO: Review/fix/adjust/tune function signatures. */ // void (*getattr)( struct Qntan_FileSystem**, const char*path, // void(*onDone)(int, struct stat*buf, Qntan_Cls), Qntan_Cls); // /* Get detail information of a file/dir. // * 'buf' is only valid until return from 'onDone'. // */ // void (*mkdir)( struct Qntan_FileSystem**, char const*path, mode_t, // void(*onDone)(int, Qntan_Cls), Qntan_Cls ); // /**/ // void (*rmdir)( struct Qntan_FileSystem**, const char*path, // void(*onDone)(int, Qntan_Cls), Qntan_Cls ); // /**/ // void (*open)( struct Qntan_FileSystem**, const char*path, // struct fuse_file_info*, void(*onDone)(int, Qntan_Cls), Qntan_Cls); // /**/ // void (*create)( struct Qntan_FileSystem**, const char*path, mode_t mode, // struct fuse_file_info*, void(*onDone)(int, Qntan_Cls), Qntan_Cls); // /**/ // void (*unlink)( struct Qntan_FileSystem**, const char*path, // void(*onDone)(int, Qntan_Cls), Qntan_Cls); // /**/ // void (*truncate)( struct Qntan_FileSystem**, char const*path, off_t size, // void(*onDone)(int, Qntan_Cls), Qntan_Cls); // /* TODO There's a duplicate in 'File' of this function. // */ void (*rename)( struct Qntan_FileSystem**, char const*src, char const*dst, void(*onDone)(int, Qntan_Cls), Qntan_Cls); /**/ // void (*chmod)( struct Qntan_FileSystem**, char const*path, mode_t, // void(*onDone)(int, Qntan_Cls), Qntan_Cls); // /**/ // void (*chown)( struct Qntan_FileSystem**, char const*path, uid_t, gid_t, // void(*onDone)(int, Qntan_Cls), Qntan_Cls); // /**/ // void (*utimens)( struct Qntan_FileSystem**, char const*path, const struct timespec, // void(*onDone)(int, Qntan_Cls), Qntan_Cls ); // /**/ // void (*release)( struct Qntan_FileSystem**, char const*path, struct fuse_file_info*, // void(*onDone)(int, Qntan_Cls), Qntan_Cls); // /**/ // /* TODO what about 'close()' ? */ // void (*fsync)( struct Qntan_FileSystem**, char const*path, int isdatasync, // struct fuse_file_info*, void(*onDone)(int, Qntan_Cls), Qntan_Cls); // /**/ }; #ifndef Qntan_FourierTransform_transform # define Qntan_FourierTransform_transform(A, ...) (*A)->transform(A, __VA_ARGS__) #endif struct Qntan_FourierTransform { /**/ int (*transform)( struct Qntan_FourierTransform**, float*samples, size_t samples_cnt, float*output ); /* WARN: There may be implementations producing odd results if * 'samples' and 'output' overlap. * @return negative values on erorr. Zero on success. */ }; struct Qntan_Process { /* TODO write doc */ void (*write)( struct Qntan_Process**, void const*buf, int buf_len, int flgs, void(*onWritten)(int ret,Qntan_Cls), Qntan_Cls ); /* Writes 'buf' to the childs stdin stream. * * @param buf * This buffer MUST stay valid, until the corresponding * 'onWritten' callback got called! * @param flgs * 0x4 set means this is last chunk. * Any other bit set is UNDEFINED BEHAVIOR! */ int (*signal)( struct Qntan_Process**, int sig ); /* https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html * * (HINT: Do not confuse 'signal' and 'kill' names here) * * Windoof has no SIGKILL. But this API suports it anyway. You can * define it as below in your app to use it: * #define SIGKILL 132 */ void (*join)( struct Qntan_Process**, int timeoutMs, void (*onDone)(int,int,int,Qntan_Cls), Qntan_Cls ); /* TODO write doc */ }; struct Qntan_HshTbl { /**/ int (*swap)( struct Qntan_HshTbl**, void*elm, void*ptrToDst ); /* Returns 0 if 'elm' got copied into the hashtable. * Returns 1 is similar to 'Return 0'. BUT: a matching element did already * exist and this old element now got swapped into 'ptrToDst'. * Returns negative values to indicate errors. */ int (*addIfNew)( struct Qntan_HshTbl**, void*elm ); /* Returns 0 if 'elm' got copied into the hashtable. * Returns '-EEXIST' (yep, negated) if 'elm' already exists. Nothing got * copied anywhere. * Returns negative values to indicate errors. */ int (*del)( struct Qntan_HshTbl**, void*srch, void*ptrToDst ); /* Returns 0 if nothing was removed (eg there's no matching object). * Returns 1 if found object got moved to 'ptrToDst'. * Returns negative values on error. */ int (*delAny)( struct Qntan_HshTbl**, void*ptrToDst ); /* Returns 0 if nothing was removed (eg there are no elements). * Returns 1 if any object got moved to 'ptrToDst'. It is UNSPECIFIED which * elements gets removed. * Returns negative values on error. */ int (*get)( struct Qntan_HshTbl**, void*srch, void*ptrToDst ); /* Returns 0 if there's no object matching 'srch'. * Returns 1 if found object got copied to 'ptrToDst'. The element itelf * will swill be present in the table. */ uintptr_t (*nObj)( struct Qntan_HshTbl** ); /* Number of objects currently present in this collection. */ struct Qntan_HshTbl_Cursor** (*newCursor)( struct Qntan_HshTbl** ); /* Initializes and returns a new cursor. The cursor MUST be passed to * 'delCursor' when no longer used. */ void (*delCursor)( struct Qntan_HshTbl**, struct Qntan_HshTbl_Cursor** ); /**/ }; struct Qntan_HshTbl_Cursor { int (*next)( struct Qntan_HshTbl_Cursor**, void*ptrToDst ); /* Returns 1 if next element got placed in 'ptrToDst'. * Returns 0 if there are no more elements to traverse. * Returns negative values on error. */ void (*del)( struct Qntan_HshTbl_Cursor**, void*ptrToDst ); /* moves the element where cursor currently points to to 'ptrToDst' and * removes it from the table. */ }; struct Qntan_Socket { void (*accept)( struct Qntan_Socket**, void(*onDone)(int ret,struct Qntan_Socket**clientSock,Qntan_Cls), Qntan_Cls ); /* Conceptually same idea as * "https://pubs.opengroup.org/onlinepubs/009696799/functions/accept.html". */ void (*send)( struct Qntan_Socket**, void*buf, int buf_len, int flgs, void(*onDone)(int ret,void*rbuf,Qntan_Cls), Qntan_Cls ); /* Based on "https://pubs.opengroup.org/onlinepubs/000095399/functions/send.html". * * @param buf, buf_len * The octets (and how many of them) to write. This 'buf' MUST stay * valid until onDone got called. * * @param flgs * (flgs & 1) indicates that data should be flushed. * (flgs & 2) indicates that after sending buf we have to act like a * call to * "https://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html" * with SHUT_WR. * All not specified flags MUST be set to zero. Passing any other flag * is UNDEFINED BEHAVIOR! * * @param onDone * The function that gets called when the send operation has completed. * Negative 'ret' indicates errors. 'rbuf' MUST be the same as 'buf'. */ void (*recv)( struct Qntan_Socket**, void*buf, int buf_len, void(*onDone)(int ret,void*buf,Qntan_Cls), Qntan_Cls ); /* Based on "https://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html". * * @param onDone.buf * MUST be the same ptr as passed via 'buf' initially. */ void (*close)( struct Qntan_Socket**, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* Based on "https://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html". * WARN: Read doc for 'send' carefully before calling 'close'! * BROKEN: Api MUST be re-designed! Pooling doesn't work with TLS this way! */ }; struct Qntan_TarEnc_Hdr { char const*path; int path_len; unsigned mode; uint32_t uid, gid; char const usrNm[32], grpNm[32]; uint64_t mTimeEpchSec; uint64_t nBodyOctets; uint8_t linkType; /* 0x30=file, 0x31=hardlink, 0x32=symlink. */ char const*link; int link_len; }; struct Qntan_TarEnc { /**/ void (*nextEntry)( struct Qntan_TarEnc**, struct Qntan_TarEnc_Hdr*hdr, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* @param hdr * The header to begin the next tar entry. From now on, 'write' * will provide the body belonging to this entry. * @param ret * Negative values on error. * Zero on success. * Any other values are UNDEFINED BEHAVIOR! */ void (*write)( struct Qntan_TarEnc**, void*buf, int buf_len, int flgs, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* @param buf * The next content chunk which belongs to the most recently * written header. * @param buf_len * How many octets to write from 'buf'. * @param flgs * 0x4 set means this is last chunk of this entry. * 0x8 set means, that the whole archive has completed. * Any other bit set is UNDEFINED BEHAVIOR! * @param ret * Negative on errors. * Count of octets successfully written. */ char const* (*getLastErrorStr)( struct Qntan_TarEnc** ); /* Returns the most recent error as a short string message. The * buffer onwership stays within the impl. So take a copy if you * need it later. */ }; struct Qntan_TarDec_Hdr { char const*path; int path_len; unsigned mode; uint32_t uid, gid; char const *usrNm; int usrNm_len; char const *grpNm; int grpNm_len; uint64_t mTimeEpchSec; uint64_t nBodyOctets; uint8_t linkType; /* 0x30=file, 0x31=hardlink, 0x32=symlink. */ char const*link; int link_len; uint32_t checksum; uint8_t filetype; /* TODO doc */ }; struct Qntan_TarDec { /**/ void (*nextHdr)( struct Qntan_TarDec**, void(*onDone)(int ret, struct Qntan_TarDec_Hdr*hdr,Qntan_Cls), Qntan_Cls ); /* @param ret * Negative values on error. * 1 (one) if 'hdr' now contains the requested header. * 0 (zero) if there are no more entries (EndOf archive reached). * @param hdr * Iff 'ret' is one, this contains the requested header. * WARN: 'hdr' (and stuff where it points to) is only valid uppon * return from 'onDone'. * WARN: for any other value of 'ret', value of 'hdr' is unspecified! */ void (*readBody)( struct Qntan_TarDec**, void*buf, int buf_cap, void(*onDone)(void*rbuf, int buf_len, int flg, Qntan_Cls), Qntan_Cls); /* @param buf * Where to write the read octets to. * @param buf_cap * Maximum count of octets to read. * @param rbuf * Same as 'buf', just for convenience to have a reference in * the callback also. * @param buf_len * How many octets actually got read and placed into 'buf'. * @param flg * 'flg & 4' indicates that there is no more data (EndOf entry * reached). */ }; struct Qntan_Cond { /* An asynchronous Conditional-Variable. */ void (*wait)( struct Qntan_Cond**, struct Qntan_Mutx**, int64_t tv_sec, int32_t tv_nsec, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* Same idea as `pthread_cond_timedwait()`. * `tv_sec` and `tv_nsec` have the same idea as in `struct timespec`. * on timeout, `onDone` will be called with `-ETIMEDOUT` (yep, negated). */ void (*bcast)( struct Qntan_Cond** ); /* Same idea as `pthread_cond_broadcast()`. */ void (*signal)( struct Qntan_Cond** ); /* Same idea as `pthread_cond_signal()`. */ }; struct Qntan_Mutx { /* Same idea as a `pthread_mutex_t`, just using virtual funcs, to * increase overkill and make some people sad :D */ int (*lock)( struct Qntan_Mutx** ); /* Like `pthread_mutex_lock()` * WARN: this call may block if mutx already locked! So make sure you * either * NEVER HOLD THE MUTX FOR TOO LONG ANYWHERE, * or * only `lock()` from threads where blocking is ok. */ int (*unlock)( struct Qntan_Mutx** ); /* Like `pthread_mutex_unlock()` */ }; struct Qntan_Networker { /**/ void (*getaddrinfo)( struct Qntan_Networker**, char const*node, int node_len, char const*service, int service_len, int(*onAddress)(int ai_flags, int ai_family, int ai_socktype, int ai_protocol, void*sockaddr, int sockaddr_len, char const*ai_canonname, Qntan_Cls), void(*onDone)(int ret, char const*errmsg, Qntan_Cls), Qntan_Cls ); /* Inspired by * "https://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html" * but tweaks the api a bit toward callbacks, so it fits better into the idea * of this libraries asynchronous nature. * * @param onAddress * MUST either return zero to indicate success or -ECANCELED (negated) * if iteration should stop. * Returning any other value is UNDEFINED BEHAVIOR! * @param onDone * called at end of operation. */ }; struct Qntan_CsvDec { /**/ void (*write)( struct Qntan_CsvDec**, void const*buf, int buf_len, int flgs, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* @param flgs * 0x4 set means this is last chunk. * Any other bit set is UNDEFINED BEHAVIOR! */ }; struct Qntan_CsvDec_Mentor { /**/ void (*onCsvDocEnd)( Qntan_Cls ); /* TODO doc */ void (*onEntityBeg)( Qntan_Cls ); /* TODO doc */ void (*onEntityEnd)( Qntan_Cls ); /* TODO doc */ void (*onAttrBeg)( Qntan_Cls ); /* TODO doc */ void (*onAttrEnd)( Qntan_Cls ); /* TODO doc */ void (*onChunkNaked)( char const*buf, int buf_len, Qntan_Cls ); /* TODO doc */ void (*onChunkQuoted)( char const*buf, int buf_len, Qntan_Cls ); /* TODO doc */ }; struct Qntan_CsvIStream { /**/ void (*write)( struct Qntan_CsvIStream**, void const*buf, int buf_len, int flgs, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* @param flgs * 0x4 set means this is last chunk. * Any other bit set is UNDEFINED BEHAVIOR! */ void (*pause)( struct Qntan_CsvIStream** ); /* TODO doc */ void (*resume)( struct Qntan_CsvIStream** ); /* TODO doc */ }; struct Qntan_CsvIStream_Mentor { /**/ void (*onCsvRow)( char const**values, int*values_len, int numCols, Qntan_Cls ); /* Called for every CSV row. * * How an implementation could look like: * void onCsvRow(char const*values, int*values_len, int numCols, Qntan_Cls a){ * for( int iCol = 0 ; iCol < numCols ; ++iCol ) * printf("col[%d]: '%.*s'\n", iCol, values_len[i], values[i]); * } * * @param values * Array of strings of which this row consists of. * @param values_len * Lengths of the strings in 'values'. * @param numCols * Number of columns present in this row. Aka number of entries present * in 'values' and 'values_len'. */ void (*onCsvDocEnd)( Qntan_Cls ); /* Called when there are no more rows. */ }; struct Qntan_JsonEnc { /**/ void (*reset)( struct Qntan_JsonEnc** ); /* throws away the current state and sets the encoder for a new run. */ void (*flush)( struct Qntan_JsonEnc** ); /* TODO: to me, looks like this should be async and take an 'onDone' cback. */ void (*objBeg)( struct Qntan_JsonEnc** ); /**/ void (*objEnd)( struct Qntan_JsonEnc** ); /**/ void (*arrBeg)( struct Qntan_JsonEnc** ); /**/ void (*arrEnd)( struct Qntan_JsonEnc** ); /**/ void (*key)( struct Qntan_JsonEnc**, char const*key, int key_len, int flgs ); /* Can be called multiple times, which will append to the currently in * progress key. The last call MUST have flg 0x4 set, to indicate end. * 'key' MUST be in utf8 encoding! * Any other flags set leads to UNDEFINED BEHAVIOR! */ void (*string)( struct Qntan_JsonEnc**, char const*str, int str_len, int flgs ); /* Can be called multiple times, which will append to the currently in * progress string. The last call MUST have flg 0x4 set, to indicate end. * 'str' MUST be in utf8 encoding! * Any other flags set leads to UNDEFINED BEHAVIOR! */ void (*number)( struct Qntan_JsonEnc**, double ); /**/ void (*boolean)( struct Qntan_JsonEnc**, int ); /**/ void (*null)( struct Qntan_JsonEnc** ); /**/ }; struct Qntan_JsonDec { /**/ void (*write)(struct Qntan_JsonDec**, void const*buf, int buf_len, int flgs, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* @param flgs * 0x4 set means this is last chunk. * Any other bit set is UNDEFINED BEHAVIOR! */ }; struct Qntan_JsonDec_Mentor { /**/ void (*onError)( Qntan_Cls cls, uintmax_t errOff ); /* Called if a parsing error occurs. 'errOff' is a byte offset measured from * the beginning of the json to the char where the error was detected. Be * prepared that the error may not be exactly at the pointed location, but * somewhere near that location. */ void (*onJsonDocEnd)( Qntan_Cls cls ); /**/ void (*onJsonObjBeg)( Qntan_Cls cls ); /**/ void (*onJsonObjEnd)( Qntan_Cls cls ); /**/ void (*onJsonArrBeg)( Qntan_Cls cls ); /**/ void (*onJsonArrEnd)( Qntan_Cls cls ); /**/ void (*onJsonNull)( Qntan_Cls cls ); /**/ void (*onJsonBool)( int val, Qntan_Cls cls ); /**/ void (*onJsonNumber)( double value, Qntan_Cls cls ); void (*onJsonStringKeyChunk)( char const*key, int key_len, Qntan_Cls cls ); /* zero-length chunk indicates EOF */ void (*onJsonStringChunk)( char const*buf, int buf_len, Qntan_Cls cls ); /* zero-length chunk indicates EOF */ }; struct Qntan_JsonTreeDec_JsonNode { /**/ char type; /* '{' object * '[' array * 'f' float (aka number) * 'b' bool * 's' string * '0' null */ struct Qntan_JsonTreeDec_JsonNode *parent; /* Is NULL for the root node. */ char *key; int key_len; /* If this node is a child in an object, its key will be stored here. So * for example in JSON '{"foo":42}' if we take current node to be * number 42, the 'key' will contain "foo". 'key_len' is number of BYTES, * NOT codepoints. */ union /* See 'type' to know which of those values is valid. */ { double valNumber; int valBool; struct/*valString*/{ char const *valStr; int valStr_len; }; struct/*object or array. For object keys see 'childs[i]->key' */{ struct Qntan_JsonTreeDec_JsonNode **childs; int childs_len; }; }; }; struct Qntan_JsonTreeDec { /**/ void (*write)( struct Qntan_JsonTreeDec**, void const*buf, int buf_len, int flg, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* flg bit 0x4 means "isLastChunk". */ }; struct Qntan_XmlDec { /**/ void (*pause)( struct Qntan_XmlDec** ); /**/ void (*resume)( struct Qntan_XmlDec** ); /**/ void (*write)( struct Qntan_XmlDec**, void const*buf, int buf_len, int flgs, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* @param flgs * 0x4 set means this is last chunk. * Any other bit set is UNDEFINED BEHAVIOR! */ }; struct Qntan_XmlDec_Mentor { /**/ void (*onXmlDocEnd)( Qntan_Cls ); /**/ void (*onElemBeg)( char const*tagName, int tagName_len, Qntan_Cls ); /**/ void (*onElemEnd)( char const*tagName, int tagName_len, Qntan_Cls ); /**/ void (*onAttr)( char const*key, char const*val, Qntan_Cls ); /**/ void (*onChunk)( char const*buf, int buf_len, Qntan_Cls ); /**/ }; struct Qntan_HttpClient_Exchg_Opts { /* WARN: HTTP IS EXPERMIMENTAL! DO NOT TRUST ANYTHING HERE! */ char const *mthd; /* Eg: 'GET', 'POST', ... */ char const *host; /* Eg: 'example.com', '127.0.0.1', ... */ uint16_t port; /* TCP port to connect to. */ char const *url; /* Eg: "/foo/bar?blubb=true" */ char **hdrs; /* Eg: {"key1", "val1", "key2", "val2", NULL} */ uint8_t isTls; /**/ char const *body; /* can be NULL, which means body gets written through separate calls. * MUST be null-byte-terminated. * MUST NOT contain null-bytes. If you have to, set NULL and use separate * write calls instead. */ Qntan_Cls cls; /**/ void (*onRspHdr)( char const*proto, int code, char const*msg, char const*const*hdrs, Qntan_Cls ); /* 'proto' looks like "HTTP/1.1". Is zero-terminated. * 'code' eg 404, simply the http response code. * 'msg' eg "Not Found", simply the http response phrase. Is zero-terminated. * 'hdrs' response headers. Same format as the request headers. */ void (*onBodyChunk)( char const*buf, int len, int flgs, Qntan_Cls ); /* @param len * Negative values indicate errors. * If positive, it indicates how long 'buf' is. * WARN: if zero or negative, value of 'buf' is unspecified! * @param flgs * 'flgs & 4' means this is last buffer (EndOfMsg). * WARN: Other flags are reserved and may hold ANY value. */ }; struct Qntan_HttpClient_Exchg { /* WARN: HTTP IS EXPERMIMENTAL! DO NOT TRUST ANYTHING HERE! */ void (*write)( struct Qntan_HttpClient_Exchg**, void*buf, int len, int flgs, void(*onDone)(int,Qntan_Cls), Qntan_Cls ); /* Write another request body chunk. * @param flgs * 'flgs & 4' means this is the last buffer (aka EndOfMsg). * WARN: Other flags are reserved and may hold ANY value. */ void (*pause)( struct Qntan_HttpClient_Exchg** ); /* Set backpressure. This means that callbacks won't be called anymore. * Events will be held back until resumed. */ void (*resume)( struct Qntan_HttpClient_Exchg** ); /* Cancel backpressure. */ }; struct Qntan_HttpClient { /* WARN: HTTP IS EXPERMIMENTAL! DO NOT TRUST ANYTHING HERE! */ void (*httpReq)( struct Qntan_HttpClient**, struct Qntan_HttpClient_Exchg_Opts*, void(*onDone)( int err, struct Qntan_HttpClient_Exchg**exchg, void(*unref)(struct Qntan_HttpClient_Exchg**), Qntan_Cls onDoneArg), Qntan_Cls onDoneArg ); /* Creates a new HTTP exchange (aka request/response). * @param onDone * Will be called with the result. * @param err * Negative on erorrs. Zero if 'exchg' is ready-to-use. * @param exchg * WARN: Only valid if 'err' is zero. The requested instance. * @param unref * The function to be called as soon 'exchg' is no longer used. * @param onDoneArg * Passed through closure (aka context). */ }; #ifndef Qntan_GfxRenderer_setScissor # define Qntan_GfxRenderer_setScissor(A, B, C, D, E) (*A)->setScissor(A, B, C, D, E) #endif #ifndef Qntan_GfxRenderer_triangleStrip2d # define Qntan_GfxRenderer_triangleStrip2d(A, B, C) (*A)->triangleStrip2d(A, B, C) #endif #ifndef Qntan_GfxRenderer_triangleStrip2dOneColor # define Qntan_GfxRenderer_triangleStrip2dOneColor(A, B, C, D) (*A)->triangleStrip2dOneColor(A, B, C, D) #endif #ifndef Qntan_GfxRenderer_circle2dOneColor # define Qntan_GfxRenderer_circle2dOneColor(A, B, C, D, E, F) (*A)->circle2dOneColor(A, B, C, D, E, F) #endif #ifndef Qntan_GfxRenderer_lineStrip2dOneColor # define Qntan_GfxRenderer_lineStrip2dOneColor(A, B, C, D, E) (*A)->lineStrip2dOneColor(A, B, C, D, E) #endif struct Qntan_GfxVtx2d { float x, y; }; struct Qntan_GfxVtx4d { float x, y, z, w; }; struct Qntan_GfxVtx2dColor { float x, y; uint32_t rgba8888; }; struct Qntan_GfxMtx4d { float m00, m01, m02, m03; float m10, m11, m12, m13; float m20, m21, m22, m23; float m30, m31, m32, m33; }; struct Qntan_GfxRenderer { /* WARN: All around graphics rendering is heavily experimental! Make * sure you're ready to handle all kind of changes here. */ void (*setScissor)( struct Qntan_GfxRenderer**, int x, int y, int w, int h ); /**/ void (*triangleStrip2d)( struct Qntan_GfxRenderer**, struct Qntan_GfxVtx2dColor const*vertices, int vertices_cnt ); /**/ void (*triangleStrip2dOneColor)( struct Qntan_GfxRenderer**, struct Qntan_GfxVtx2d const*vertices, int vertices_cnt, uint32_t rgba8888 ); /**/ void (*circle2dOneColor)( struct Qntan_GfxRenderer**, int x, int y, int w, int h, uint32_t colorRGBA8888 ); /* @param x NOT center. * @param y NOT center. * @param w horizontal diameter. * @param h vertical diameter. */ void (*lineStrip2dOneColor)( struct Qntan_GfxRenderer**, struct Qntan_GfxVtx2d const*vertices, int vertices_cnt, float lineWidth, uint32_t rgba8888 ); /**/ }; struct Qntan_JavaBytecodeParser { /**/ void (*write)( struct Qntan_JavaBytecodeParser**, char const*buf, int buf_len, int flgs, void(*onDone)(int ret,Qntan_Cls), Qntan_Cls ); /* @param flgs * 0x4 set means this is last chunk. * Any other bit set is UNDEFINED BEHAVIOR! */ }; struct Qntan_JavaBytecodeParser_Mentor { /* WARN: Be aware that ConstPool indexes are ONE based as by the java * specification. */ void (*onMagic)( uint32_t magic, struct Qntan_JavaBytecodeParser_Mentor** ); /**/ void (*onClassfileVersion)( int major, int minor, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolBegin)( int poolSize, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolUtf8)( int poolNr, char const*buf, int buf_len, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolInteger)( int poolNr, int32_t intValue, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolFloat)( int poolNr, float value, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolLong)( int poolNr, int64_t value, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolDouble)( int poolNr, double value, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolStrRef)( int poolNr, int dstIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolClassRef)( int poolNr, int nameIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolMethodRef)( int poolNr, int classIdx, int nameAndTypeIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolIfaceMethodRef)( int poolNr, int nameIdx, int nameAndTypeIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolFieldRef)( int poolNr, int nameIdx, int nameAndTypeIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolNameAndType)( int poolNr, int nameIdx, int typeIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolMethodHandle)( int poolNr, int refKind, int refIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolMethodType)( int poolNr, int descrIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolInvokeDynamic)( int poolNr, int bootstrapMethodAttrIdx, int nameAndTypeIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolModule)( int poolNr, uint16_t nameIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolPackage)( int poolNr, uint16_t nameIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onConstPoolEnd)( struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onAccessFlags)( uint16_t accessFlags, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onThisClass)( int nameIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onSuperClass)( int nameIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onIfacesBegin)( int numIfaces, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onIface)( int iIface, int classIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onIfacesEnd)( struct Qntan_JavaBytecodeParser_Mentor**cls ); /* TODO is this cback really needed? */ void (*onFieldsBegin)( uint16_t numFields, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onField)( uint16_t poolIdx, uint16_t accessFlags, uint16_t nameIdx, uint16_t descrIdx, uint16_t numAttrs, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onMethodsBegin)( int numMethods, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onMethod)( uint16_t accessFlags, int nameIdx, int descrIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onClassAttrsBegin)( int numAttrs, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onAnnotRtVisible)( uint16_t typeIdx, uint16_t numKeyValPairs, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onAnnotRtInVisible)( uint16_t typeIdx, uint16_t numKeyValPairs, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onAnnotKeyValPair)( uint8_t type, uint16_t typeNameIdx, uint16_t constNameIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onAnnotKey)( uint8_t type, uint16_t typeNameIdx, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onGenericAttribute)( int nameIdx, uint32_t bodyLength, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onGenericAttributeContent)( uint8_t const*buf, int buf_len, struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ void (*onEnd)( struct Qntan_JavaBytecodeParser_Mentor**cls ); /**/ }; struct Qntan_CamtAccount { char iban[32]; char ccy[4]; }; struct Qntan_CamtTransaction { int valueDate_cap, valueDate_len; char *valueDate; int bookDate_cap , bookDate_len ; char *bookDate ; char isCrdt, isDbit; char ccy[4]; int amtDst_cap , amtDst_len ; char *amtDst ; int amtSrc_cap , amtSrc_len ; char *amtSrc ; int dstIban_cap , dstIban_len ; char *dstIban ; int srcIban_cap , srcIban_len ; char *srcIban ; int ustrd_cap , ustrd_len ; char *ustrd ; int addtlInf_cap , addtlInf_len ; char *addtlInf ; int qrRef_cap , qrRef_len ; char *qrRef ; }; struct Qntan_CamtDec_Mentor { /**/ void (*onAccount)( struct Qntan_CamtDec_Mentor**, struct Qntan_CamtAccount*, void(*onDone)(Qntan_Cls), Qntan_Cls ); /**/ void (*onRecord)( struct Qntan_CamtDec_Mentor**, struct Qntan_CamtTransaction*, void(*onDone)(Qntan_Cls), Qntan_Cls ); /**/ }; struct Qntan_CamtDec { /**/ void (*write)( struct Qntan_CamtDec**, void*buf, int buf_len, int flgs, void(*onDone)(int,Qntan_Cls), Qntan_Cls ); /* @param flgs * 0x4 set means this is last chunk. * Any other bit set is UNDEFINED BEHAVIOR! */ }; #if __cplusplus } /* extern "C" */ #endif #endif /* INCGUARD_aM91R0ljMWoqtn7F */