diff options
| author | ruki <[email protected]> | 2017-08-15 13:39:50 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2017-08-15 13:44:27 +0800 |
| commit | b92d83c523045d7e8b716dc0610b88b0d357575f (patch) | |
| tree | 161cebb851686c2b140ca53451089d4faca307d0 | |
| parent | f7083cb5c14a5cf84c9c0ccd07891a251ec39b35 (diff) | |
remove some unused codes
170 files changed, 0 insertions, 47174 deletions
diff --git a/core/src/luajit/dynasm/dasm_arm.h b/core/src/luajit/dynasm/dasm_arm.h deleted file mode 100644 index 57e0116f5..000000000 --- a/core/src/luajit/dynasm/dasm_arm.h +++ /dev/null @@ -1,456 +0,0 @@ -/* -** DynASM ARM encoding engine. -** Copyright (C) 2005-2015 Mike Pall. All rights reserved. -** Released under the MIT license. See dynasm.lua for full copyright notice. -*/ - -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> - -#define DASM_ARCH "arm" - -#ifndef DASM_EXTERN -#define DASM_EXTERN(a,b,c,d) 0 -#endif - -/* Action definitions. */ -enum { - DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT, - /* The following actions need a buffer position. */ - DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, - /* The following actions also have an argument. */ - DASM_REL_PC, DASM_LABEL_PC, - DASM_IMM, DASM_IMM12, DASM_IMM16, DASM_IMML8, DASM_IMML12, DASM_IMMV8, - DASM__MAX -}; - -/* Maximum number of section buffer positions for a single dasm_put() call. */ -#define DASM_MAXSECPOS 25 - -/* DynASM encoder status codes. Action list offset or number are or'ed in. */ -#define DASM_S_OK 0x00000000 -#define DASM_S_NOMEM 0x01000000 -#define DASM_S_PHASE 0x02000000 -#define DASM_S_MATCH_SEC 0x03000000 -#define DASM_S_RANGE_I 0x11000000 -#define DASM_S_RANGE_SEC 0x12000000 -#define DASM_S_RANGE_LG 0x13000000 -#define DASM_S_RANGE_PC 0x14000000 -#define DASM_S_RANGE_REL 0x15000000 -#define DASM_S_UNDEF_LG 0x21000000 -#define DASM_S_UNDEF_PC 0x22000000 - -/* Macros to convert positions (8 bit section + 24 bit index). */ -#define DASM_POS2IDX(pos) ((pos)&0x00ffffff) -#define DASM_POS2BIAS(pos) ((pos)&0xff000000) -#define DASM_SEC2POS(sec) ((sec)<<24) -#define DASM_POS2SEC(pos) ((pos)>>24) -#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) - -/* Action list type. */ -typedef const unsigned int *dasm_ActList; - -/* Per-section structure. */ -typedef struct dasm_Section { - int *rbuf; /* Biased buffer pointer (negative section bias). */ - int *buf; /* True buffer pointer. */ - size_t bsize; /* Buffer size in bytes. */ - int pos; /* Biased buffer position. */ - int epos; /* End of biased buffer position - max single put. */ - int ofs; /* Byte offset into section. */ -} dasm_Section; - -/* Core structure holding the DynASM encoding state. */ -struct dasm_State { - size_t psize; /* Allocated size of this structure. */ - dasm_ActList actionlist; /* Current actionlist pointer. */ - int *lglabels; /* Local/global chain/pos ptrs. */ - size_t lgsize; - int *pclabels; /* PC label chains/pos ptrs. */ - size_t pcsize; - void **globals; /* Array of globals (bias -10). */ - dasm_Section *section; /* Pointer to active section. */ - size_t codesize; /* Total size of all code sections. */ - int maxsection; /* 0 <= sectionidx < maxsection. */ - int status; /* Status code. */ - dasm_Section sections[1]; /* All sections. Alloc-extended. */ -}; - -/* The size of the core structure depends on the max. number of sections. */ -#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) - - -/* Initialize DynASM state. */ -void dasm_init(Dst_DECL, int maxsection) -{ - dasm_State *D; - size_t psz = 0; - int i; - Dst_REF = NULL; - DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); - D = Dst_REF; - D->psize = psz; - D->lglabels = NULL; - D->lgsize = 0; - D->pclabels = NULL; - D->pcsize = 0; - D->globals = NULL; - D->maxsection = maxsection; - for (i = 0; i < maxsection; i++) { - D->sections[i].buf = NULL; /* Need this for pass3. */ - D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); - D->sections[i].bsize = 0; - D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ - } -} - -/* Free DynASM state. */ -void dasm_free(Dst_DECL) -{ - dasm_State *D = Dst_REF; - int i; - for (i = 0; i < D->maxsection; i++) - if (D->sections[i].buf) - DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); - if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); - if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); - DASM_M_FREE(Dst, D, D->psize); -} - -/* Setup global label array. Must be called before dasm_setup(). */ -void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) -{ - dasm_State *D = Dst_REF; - D->globals = gl - 10; /* Negative bias to compensate for locals. */ - DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); -} - -/* Grow PC label array. Can be called after dasm_setup(), too. */ -void dasm_growpc(Dst_DECL, unsigned int maxpc) -{ - dasm_State *D = Dst_REF; - size_t osz = D->pcsize; - DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); - memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); -} - -/* Setup encoder. */ -void dasm_setup(Dst_DECL, const void *actionlist) -{ - dasm_State *D = Dst_REF; - int i; - D->actionlist = (dasm_ActList)actionlist; - D->status = DASM_S_OK; - D->section = &D->sections[0]; - memset((void *)D->lglabels, 0, D->lgsize); - if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); - for (i = 0; i < D->maxsection; i++) { - D->sections[i].pos = DASM_SEC2POS(i); - D->sections[i].ofs = 0; - } -} - - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) { \ - D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0) -#define CKPL(kind, st) \ - do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ - D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0) -#else -#define CK(x, st) ((void)0) -#define CKPL(kind, st) ((void)0) -#endif - -static int dasm_imm12(unsigned int n) -{ - int i; - for (i = 0; i < 16; i++, n = (n << 2) | (n >> 30)) - if (n <= 255) return (int)(n + (i << 8)); - return -1; -} - -/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ -void dasm_put(Dst_DECL, int start, ...) -{ - va_list ap; - dasm_State *D = Dst_REF; - dasm_ActList p = D->actionlist + start; - dasm_Section *sec = D->section; - int pos = sec->pos, ofs = sec->ofs; - int *b; - - if (pos >= sec->epos) { - DASM_M_GROW(Dst, int, sec->buf, sec->bsize, - sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); - sec->rbuf = sec->buf - DASM_POS2BIAS(pos); - sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); - } - - b = sec->rbuf; - b[pos++] = start; - - va_start(ap, start); - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - if (action >= DASM__MAX) { - ofs += 4; - } else { - int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0; - switch (action) { - case DASM_STOP: goto stop; - case DASM_SECTION: - n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); - D->section = &D->sections[n]; goto stop; - case DASM_ESC: p++; ofs += 4; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; - case DASM_REL_LG: - n = (ins & 2047) - 10; pl = D->lglabels + n; - /* Bkwd rel or global. */ - if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; } - pl += 10; n = *pl; - if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ - goto linkrel; - case DASM_REL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putrel: - n = *pl; - if (n < 0) { /* Label exists. Get label pos and store it. */ - b[pos] = -n; - } else { - linkrel: - b[pos] = n; /* Else link to rel chain, anchored at label. */ - *pl = pos; - } - pos++; - break; - case DASM_LABEL_LG: - pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; - case DASM_LABEL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putlabel: - n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; - } - *pl = -pos; /* Label exists now. */ - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_IMM: - case DASM_IMM16: -#ifdef DASM_CHECKS - CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); - if ((ins & 0x8000)) - CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I); - else - CK((n>>((ins>>5)&31)) == 0, RANGE_I); -#endif - b[pos++] = n; - break; - case DASM_IMMV8: - CK((n & 3) == 0, RANGE_I); - n >>= 2; - case DASM_IMML8: - case DASM_IMML12: - CK(n >= 0 ? ((n>>((ins>>5)&31)) == 0) : - (((-n)>>((ins>>5)&31)) == 0), RANGE_I); - b[pos++] = n; - break; - case DASM_IMM12: - CK(dasm_imm12((unsigned int)n) != -1, RANGE_I); - b[pos++] = n; - break; - } - } - } -stop: - va_end(ap); - sec->pos = pos; - sec->ofs = ofs; -} -#undef CK - -/* Pass 2: Link sections, shrink aligns, fix label offsets. */ -int dasm_link(Dst_DECL, size_t *szp) -{ - dasm_State *D = Dst_REF; - int secnum; - int ofs = 0; - -#ifdef DASM_CHECKS - *szp = 0; - if (D->status != DASM_S_OK) return D->status; - { - int pc; - for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) - if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; - } -#endif - - { /* Handle globals not defined in this translation unit. */ - int idx; - for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { - int n = D->lglabels[idx]; - /* Undefined label: Collapse rel chain and replace with marker (< 0). */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } - } - } - - /* Combine all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->rbuf; - int pos = DASM_SEC2POS(secnum); - int lastpos = sec->pos; - - while (pos != lastpos) { - dasm_ActList p = D->actionlist + b[pos++]; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: p++; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; - case DASM_REL_LG: case DASM_REL_PC: pos++; break; - case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; - case DASM_IMM: case DASM_IMM12: case DASM_IMM16: - case DASM_IMML8: case DASM_IMML12: case DASM_IMMV8: pos++; break; - } - } - stop: (void)0; - } - ofs += sec->ofs; /* Next section starts right after current section. */ - } - - D->codesize = ofs; /* Total size of all code sections */ - *szp = ofs; - return DASM_S_OK; -} - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0) -#else -#define CK(x, st) ((void)0) -#endif - -/* Pass 3: Encode sections. */ -int dasm_encode(Dst_DECL, void *buffer) -{ - dasm_State *D = Dst_REF; - char *base = (char *)buffer; - unsigned int *cp = (unsigned int *)buffer; - int secnum; - - /* Encode all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->buf; - int *endb = sec->rbuf + sec->pos; - - while (b != endb) { - dasm_ActList p = D->actionlist + *b++; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0; - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: *cp++ = *p++; break; - case DASM_REL_EXT: - n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048)); - goto patchrel; - case DASM_ALIGN: - ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; - break; - case DASM_REL_LG: - CK(n >= 0, UNDEF_LG); - case DASM_REL_PC: - CK(n >= 0, UNDEF_PC); - n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) - 4; - patchrel: - if ((ins & 0x800) == 0) { - CK((n & 3) == 0 && ((n+0x02000000) >> 26) == 0, RANGE_REL); - cp[-1] |= ((n >> 2) & 0x00ffffff); - } else if ((ins & 0x1000)) { - CK((n & 3) == 0 && -256 <= n && n <= 256, RANGE_REL); - goto patchimml8; - } else if ((ins & 0x2000) == 0) { - CK((n & 3) == 0 && -4096 <= n && n <= 4096, RANGE_REL); - goto patchimml; - } else { - CK((n & 3) == 0 && -1020 <= n && n <= 1020, RANGE_REL); - n >>= 2; - goto patchimml; - } - break; - case DASM_LABEL_LG: - ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); - break; - case DASM_LABEL_PC: break; - case DASM_IMM: - cp[-1] |= ((n>>((ins>>10)&31)) & ((1<<((ins>>5)&31))-1)) << (ins&31); - break; - case DASM_IMM12: - cp[-1] |= dasm_imm12((unsigned int)n); - break; - case DASM_IMM16: - cp[-1] |= ((n & 0xf000) << 4) | (n & 0x0fff); - break; - case DASM_IMML8: patchimml8: - cp[-1] |= n >= 0 ? (0x00800000 | (n & 0x0f) | ((n & 0xf0) << 4)) : - ((-n & 0x0f) | ((-n & 0xf0) << 4)); - break; - case DASM_IMML12: case DASM_IMMV8: patchimml: - cp[-1] |= n >= 0 ? (0x00800000 | n) : (-n); - break; - default: *cp++ = ins; break; - } - } - stop: (void)0; - } - } - - if (base + D->codesize != (char *)cp) /* Check for phase errors. */ - return DASM_S_PHASE; - return DASM_S_OK; -} -#undef CK - -/* Get PC label offset. */ -int dasm_getpclabel(Dst_DECL, unsigned int pc) -{ - dasm_State *D = Dst_REF; - if (pc*sizeof(int) < D->pcsize) { - int pos = D->pclabels[pc]; - if (pos < 0) return *DASM_POS2PTR(D, -pos); - if (pos > 0) return -1; /* Undefined. */ - } - return -2; /* Unused or out of range. */ -} - -#ifdef DASM_CHECKS -/* Optional sanity checker to call between isolated encoding steps. */ -int dasm_checkstep(Dst_DECL, int secmatch) -{ - dasm_State *D = Dst_REF; - if (D->status == DASM_S_OK) { - int i; - for (i = 1; i <= 9; i++) { - if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; } - D->lglabels[i] = 0; - } - } - if (D->status == DASM_S_OK && secmatch >= 0 && - D->section != &D->sections[secmatch]) - D->status = DASM_S_MATCH_SEC|(D->section-D->sections); - return D->status; -} -#endif - diff --git a/core/src/luajit/dynasm/dasm_arm.lua b/core/src/luajit/dynasm/dasm_arm.lua deleted file mode 100644 index 90a259c5c..000000000 --- a/core/src/luajit/dynasm/dasm_arm.lua +++ /dev/null @@ -1,1125 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM ARM module. --- --- Copyright (C) 2005-2015 Mike Pall. All rights reserved. --- See dynasm.lua for full copyright notice. ------------------------------------------------------------------------------- - --- Module information: -local _info = { - arch = "arm", - description = "DynASM ARM module", - version = "1.3.0", - vernum = 10300, - release = "2011-05-05", - author = "Mike Pall", - license = "MIT", -} - --- Exported glue functions for the arch-specific module. -local _M = { _info = _info } - --- Cache library functions. -local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs -local assert, setmetatable, rawget = assert, setmetatable, rawget -local _s = string -local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char -local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub -local concat, sort, insert = table.concat, table.sort, table.insert -local bit = bit or require("bit") -local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift -local ror, tohex = bit.ror, bit.tohex - --- Inherited tables and callbacks. -local g_opt, g_arch -local wline, werror, wfatal, wwarn - --- Action name list. --- CHECK: Keep this in sync with the C code! -local action_names = { - "STOP", "SECTION", "ESC", "REL_EXT", - "ALIGN", "REL_LG", "LABEL_LG", - "REL_PC", "LABEL_PC", "IMM", "IMM12", "IMM16", "IMML8", "IMML12", "IMMV8", -} - --- Maximum number of section buffer positions for dasm_put(). --- CHECK: Keep this in sync with the C code! -local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. - --- Action name -> action number. -local map_action = {} -for n,name in ipairs(action_names) do - map_action[name] = n-1 -end - --- Action list buffer. -local actlist = {} - --- Argument list for next dasm_put(). Start with offset 0 into action list. -local actargs = { 0 } - --- Current number of section buffer positions for dasm_put(). -local secpos = 1 - ------------------------------------------------------------------------------- - --- Dump action names and numbers. -local function dumpactions(out) - out:write("DynASM encoding engine action codes:\n") - for n,name in ipairs(action_names) do - local num = map_action[name] - out:write(format(" %-10s %02X %d\n", name, num, num)) - end - out:write("\n") -end - --- Write action list buffer as a huge static C array. -local function writeactions(out, name) - local nn = #actlist - if nn == 0 then nn = 1; actlist[0] = map_action.STOP end - out:write("static const unsigned int ", name, "[", nn, "] = {\n") - for i = 1,nn-1 do - assert(out:write("0x", tohex(actlist[i]), ",\n")) - end - assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) -end - ------------------------------------------------------------------------------- - --- Add word to action list. -local function wputxw(n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - actlist[#actlist+1] = n -end - --- Add action to list with optional arg. Advance buffer pos, too. -local function waction(action, val, a, num) - local w = assert(map_action[action], "bad action name `"..action.."'") - wputxw(w * 0x10000 + (val or 0)) - if a then actargs[#actargs+1] = a end - if a or num then secpos = secpos + (num or 1) end -end - --- Flush action list (intervening C code or buffer pos overflow). -local function wflush(term) - if #actlist == actargs[1] then return end -- Nothing to flush. - if not term then waction("STOP") end -- Terminate action list. - wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) - actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). - secpos = 1 -- The actionlist offset occupies a buffer position, too. -end - --- Put escaped word. -local function wputw(n) - if n <= 0x000fffff then waction("ESC") end - wputxw(n) -end - --- Reserve position for word. -local function wpos() - local pos = #actlist+1 - actlist[pos] = "" - return pos -end - --- Store word to reserved position. -local function wputpos(pos, n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - if n <= 0x000fffff then - insert(actlist, pos+1, n) - n = map_action.ESC * 0x10000 - end - actlist[pos] = n -end - ------------------------------------------------------------------------------- - --- Global label name -> global label number. With auto assignment on 1st use. -local next_global = 20 -local map_global = setmetatable({}, { __index = function(t, name) - if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end - local n = next_global - if n > 2047 then werror("too many global labels") end - next_global = n + 1 - t[name] = n - return n -end}) - --- Dump global labels. -local function dumpglobals(out, lvl) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("Global labels:\n") - for i=20,next_global-1 do - out:write(format(" %s\n", t[i])) - end - out:write("\n") -end - --- Write global label enum. -local function writeglobals(out, prefix) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("enum {\n") - for i=20,next_global-1 do - out:write(" ", prefix, t[i], ",\n") - end - out:write(" ", prefix, "_MAX\n};\n") -end - --- Write global label names. -local function writeglobalnames(out, name) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("static const char *const ", name, "[] = {\n") - for i=20,next_global-1 do - out:write(" \"", t[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Extern label name -> extern label number. With auto assignment on 1st use. -local next_extern = 0 -local map_extern_ = {} -local map_extern = setmetatable({}, { __index = function(t, name) - -- No restrictions on the name for now. - local n = next_extern - if n > 2047 then werror("too many extern labels") end - next_extern = n + 1 - t[name] = n - map_extern_[n] = name - return n -end}) - --- Dump extern labels. -local function dumpexterns(out, lvl) - out:write("Extern labels:\n") - for i=0,next_extern-1 do - out:write(format(" %s\n", map_extern_[i])) - end - out:write("\n") -end - --- Write extern label names. -local function writeexternnames(out, name) - out:write("static const char *const ", name, "[] = {\n") - for i=0,next_extern-1 do - out:write(" \"", map_extern_[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Arch-specific maps. - --- Ext. register name -> int. name. -local map_archdef = { sp = "r13", lr = "r14", pc = "r15", } - --- Int. register name -> ext. name. -local map_reg_rev = { r13 = "sp", r14 = "lr", r15 = "pc", } - -local map_type = {} -- Type name -> { ctype, reg } -local ctypenum = 0 -- Type number (for Dt... macros). - --- Reverse defines for registers. -function _M.revdef(s) - return map_reg_rev[s] or s -end - -local map_shift = { lsl = 0, lsr = 1, asr = 2, ror = 3, } - -local map_cond = { - eq = 0, ne = 1, cs = 2, cc = 3, mi = 4, pl = 5, vs = 6, vc = 7, - hi = 8, ls = 9, ge = 10, lt = 11, gt = 12, le = 13, al = 14, - hs = 2, lo = 3, -} - ------------------------------------------------------------------------------- - --- Template strings for ARM instructions. -local map_op = { - -- Basic data processing instructions. - and_3 = "e0000000DNPs", - eor_3 = "e0200000DNPs", - sub_3 = "e0400000DNPs", - rsb_3 = "e0600000DNPs", - add_3 = "e0800000DNPs", - adc_3 = "e0a00000DNPs", - sbc_3 = "e0c00000DNPs", - rsc_3 = "e0e00000DNPs", - tst_2 = "e1100000NP", - teq_2 = "e1300000NP", - cmp_2 = "e1500000NP", - cmn_2 = "e1700000NP", - orr_3 = "e1800000DNPs", - mov_2 = "e1a00000DPs", - bic_3 = "e1c00000DNPs", - mvn_2 = "e1e00000DPs", - - and_4 = "e0000000DNMps", - eor_4 = "e0200000DNMps", - sub_4 = "e0400000DNMps", - rsb_4 = "e0600000DNMps", - add_4 = "e0800000DNMps", - adc_4 = "e0a00000DNMps", - sbc_4 = "e0c00000DNMps", - rsc_4 = "e0e00000DNMps", - tst_3 = "e1100000NMp", - teq_3 = "e1300000NMp", - cmp_3 = "e1500000NMp", - cmn_3 = "e1700000NMp", - orr_4 = "e1800000DNMps", - mov_3 = "e1a00000DMps", - bic_4 = "e1c00000DNMps", - mvn_3 = "e1e00000DMps", - - lsl_3 = "e1a00000DMws", - lsr_3 = "e1a00020DMws", - asr_3 = "e1a00040DMws", - ror_3 = "e1a00060DMws", - rrx_2 = "e1a00060DMs", - - -- Multiply and multiply-accumulate. - mul_3 = "e0000090NMSs", - mla_4 = "e0200090NMSDs", - umaal_4 = "e0400090DNMSs", -- v6 - mls_4 = "e0600090DNMSs", -- v6T2 - umull_4 = "e0800090DNMSs", - umlal_4 = "e0a00090DNMSs", - smull_4 = "e0c00090DNMSs", - smlal_4 = "e0e00090DNMSs", - - -- Halfword multiply and multiply-accumulate. - smlabb_4 = "e1000080NMSD", -- v5TE - smlatb_4 = "e10000a0NMSD", -- v5TE - smlabt_4 = "e10000c0NMSD", -- v5TE - smlatt_4 = "e10000e0NMSD", -- v5TE - smlawb_4 = "e1200080NMSD", -- v5TE - smulwb_3 = "e12000a0NMS", -- v5TE - smlawt_4 = "e12000c0NMSD", -- v5TE - smulwt_3 = "e12000e0NMS", -- v5TE - smlalbb_4 = "e1400080NMSD", -- v5TE - smlaltb_4 = "e14000a0NMSD", -- v5TE - smlalbt_4 = "e14000c0NMSD", -- v5TE - smlaltt_4 = "e14000e0NMSD", -- v5TE - smulbb_3 = "e1600080NMS", -- v5TE - smultb_3 = "e16000a0NMS", -- v5TE - smulbt_3 = "e16000c0NMS", -- v5TE - smultt_3 = "e16000e0NMS", -- v5TE - - -- Miscellaneous data processing instructions. - clz_2 = "e16f0f10DM", -- v5T - rev_2 = "e6bf0f30DM", -- v6 - rev16_2 = "e6bf0fb0DM", -- v6 - revsh_2 = "e6ff0fb0DM", -- v6 - sel_3 = "e6800fb0DNM", -- v6 - usad8_3 = "e780f010NMS", -- v6 - usada8_4 = "e7800010NMSD", -- v6 - rbit_2 = "e6ff0f30DM", -- v6T2 - movw_2 = "e3000000DW", -- v6T2 - movt_2 = "e3400000DW", -- v6T2 - -- Note: the X encodes width-1, not width. - sbfx_4 = "e7a00050DMvX", -- v6T2 - ubfx_4 = "e7e00050DMvX", -- v6T2 - -- Note: the X encodes the msb field, not the width. - bfc_3 = "e7c0001fDvX", -- v6T2 - bfi_4 = "e7c00010DMvX", -- v6T2 - - -- Packing and unpacking instructions. - pkhbt_3 = "e6800010DNM", pkhbt_4 = "e6800010DNMv", -- v6 - pkhtb_3 = "e6800050DNM", pkhtb_4 = "e6800050DNMv", -- v6 - sxtab_3 = "e6a00070DNM", sxtab_4 = "e6a00070DNMv", -- v6 - sxtab16_3 = "e6800070DNM", sxtab16_4 = "e6800070DNMv", -- v6 - sxtah_3 = "e6b00070DNM", sxtah_4 = "e6b00070DNMv", -- v6 - sxtb_2 = "e6af0070DM", sxtb_3 = "e6af0070DMv", -- v6 - sxtb16_2 = "e68f0070DM", sxtb16_3 = "e68f0070DMv", -- v6 - sxth_2 = "e6bf0070DM", sxth_3 = "e6bf0070DMv", -- v6 - uxtab_3 = "e6e00070DNM", uxtab_4 = "e6e00070DNMv", -- v6 - uxtab16_3 = "e6c00070DNM", uxtab16_4 = "e6c00070DNMv", -- v6 - uxtah_3 = "e6f00070DNM", uxtah_4 = "e6f00070DNMv", -- v6 - uxtb_2 = "e6ef0070DM", uxtb_3 = "e6ef0070DMv", -- v6 - uxtb16_2 = "e6cf0070DM", uxtb16_3 = "e6cf0070DMv", -- v6 - uxth_2 = "e6ff0070DM", uxth_3 = "e6ff0070DMv", -- v6 - - -- Saturating instructions. - qadd_3 = "e1000050DMN", -- v5TE - qsub_3 = "e1200050DMN", -- v5TE - qdadd_3 = "e1400050DMN", -- v5TE - qdsub_3 = "e1600050DMN", -- v5TE - -- Note: the X for ssat* encodes sat_imm-1, not sat_imm. - ssat_3 = "e6a00010DXM", ssat_4 = "e6a00010DXMp", -- v6 - usat_3 = "e6e00010DXM", usat_4 = "e6e00010DXMp", -- v6 - ssat16_3 = "e6a00f30DXM", -- v6 - usat16_3 = "e6e00f30DXM", -- v6 - - -- Parallel addition and subtraction. - sadd16_3 = "e6100f10DNM", -- v6 - sasx_3 = "e6100f30DNM", -- v6 - ssax_3 = "e6100f50DNM", -- v6 - ssub16_3 = "e6100f70DNM", -- v6 - sadd8_3 = "e6100f90DNM", -- v6 - ssub8_3 = "e6100ff0DNM", -- v6 - qadd16_3 = "e6200f10DNM", -- v6 - qasx_3 = "e6200f30DNM", -- v6 - qsax_3 = "e6200f50DNM", -- v6 - qsub16_3 = "e6200f70DNM", -- v6 - qadd8_3 = "e6200f90DNM", -- v6 - qsub8_3 = "e6200ff0DNM", -- v6 - shadd16_3 = "e6300f10DNM", -- v6 - shasx_3 = "e6300f30DNM", -- v6 - shsax_3 = "e6300f50DNM", -- v6 - shsub16_3 = "e6300f70DNM", -- v6 - shadd8_3 = "e6300f90DNM", -- v6 - shsub8_3 = "e6300ff0DNM", -- v6 - uadd16_3 = "e6500f10DNM", -- v6 - uasx_3 = "e6500f30DNM", -- v6 - usax_3 = "e6500f50DNM", -- v6 - usub16_3 = "e6500f70DNM", -- v6 - uadd8_3 = "e6500f90DNM", -- v6 - usub8_3 = "e6500ff0DNM", -- v6 - uqadd16_3 = "e6600f10DNM", -- v6 - uqasx_3 = "e6600f30DNM", -- v6 - uqsax_3 = "e6600f50DNM", -- v6 - uqsub16_3 = "e6600f70DNM", -- v6 - uqadd8_3 = "e6600f90DNM", -- v6 - uqsub8_3 = "e6600ff0DNM", -- v6 - uhadd16_3 = "e6700f10DNM", -- v6 - uhasx_3 = "e6700f30DNM", -- v6 - uhsax_3 = "e6700f50DNM", -- v6 - uhsub16_3 = "e6700f70DNM", -- v6 - uhadd8_3 = "e6700f90DNM", -- v6 - uhsub8_3 = "e6700ff0DNM", -- v6 - - -- Load/store instructions. - str_2 = "e4000000DL", str_3 = "e4000000DL", str_4 = "e4000000DL", - strb_2 = "e4400000DL", strb_3 = "e4400000DL", strb_4 = "e4400000DL", - ldr_2 = "e4100000DL", ldr_3 = "e4100000DL", ldr_4 = "e4100000DL", - ldrb_2 = "e4500000DL", ldrb_3 = "e4500000DL", ldrb_4 = "e4500000DL", - strh_2 = "e00000b0DL", strh_3 = "e00000b0DL", - ldrh_2 = "e01000b0DL", ldrh_3 = "e01000b0DL", - ldrd_2 = "e00000d0DL", ldrd_3 = "e00000d0DL", -- v5TE - ldrsb_2 = "e01000d0DL", ldrsb_3 = "e01000d0DL", - strd_2 = "e00000f0DL", strd_3 = "e00000f0DL", -- v5TE - ldrsh_2 = "e01000f0DL", ldrsh_3 = "e01000f0DL", - - ldm_2 = "e8900000oR", ldmia_2 = "e8900000oR", ldmfd_2 = "e8900000oR", - ldmda_2 = "e8100000oR", ldmfa_2 = "e8100000oR", - ldmdb_2 = "e9100000oR", ldmea_2 = "e9100000oR", - ldmib_2 = "e9900000oR", ldmed_2 = "e9900000oR", - stm_2 = "e8800000oR", stmia_2 = "e8800000oR", stmfd_2 = "e8800000oR", - stmda_2 = "e8000000oR", stmfa_2 = "e8000000oR", - stmdb_2 = "e9000000oR", stmea_2 = "e9000000oR", - stmib_2 = "e9800000oR", stmed_2 = "e9800000oR", - pop_1 = "e8bd0000R", push_1 = "e92d0000R", - - -- Branch instructions. - b_1 = "ea000000B", - bl_1 = "eb000000B", - blx_1 = "e12fff30C", - bx_1 = "e12fff10M", - - -- Miscellaneous instructions. - nop_0 = "e1a00000", - mrs_1 = "e10f0000D", - bkpt_1 = "e1200070K", -- v5T - svc_1 = "ef000000T", swi_1 = "ef000000T", - ud_0 = "e7f001f0", - - -- VFP instructions. - ["vadd.f32_3"] = "ee300a00dnm", - ["vadd.f64_3"] = "ee300b00Gdnm", - ["vsub.f32_3"] = "ee300a40dnm", - ["vsub.f64_3"] = "ee300b40Gdnm", - ["vmul.f32_3"] = "ee200a00dnm", - ["vmul.f64_3"] = "ee200b00Gdnm", - ["vnmul.f32_3"] = "ee200a40dnm", - ["vnmul.f64_3"] = "ee200b40Gdnm", - ["vmla.f32_3"] = "ee000a00dnm", - ["vmla.f64_3"] = "ee000b00Gdnm", - ["vmls.f32_3"] = "ee000a40dnm", - ["vmls.f64_3"] = "ee000b40Gdnm", - ["vnmla.f32_3"] = "ee100a40dnm", - ["vnmla.f64_3"] = "ee100b40Gdnm", - ["vnmls.f32_3"] = "ee100a00dnm", - ["vnmls.f64_3"] = "ee100b00Gdnm", - ["vdiv.f32_3"] = "ee800a00dnm", - ["vdiv.f64_3"] = "ee800b00Gdnm", - - ["vabs.f32_2"] = "eeb00ac0dm", - ["vabs.f64_2"] = "eeb00bc0Gdm", - ["vneg.f32_2"] = "eeb10a40dm", - ["vneg.f64_2"] = "eeb10b40Gdm", - ["vsqrt.f32_2"] = "eeb10ac0dm", - ["vsqrt.f64_2"] = "eeb10bc0Gdm", - ["vcmp.f32_2"] = "eeb40a40dm", - ["vcmp.f64_2"] = "eeb40b40Gdm", - ["vcmpe.f32_2"] = "eeb40ac0dm", - ["vcmpe.f64_2"] = "eeb40bc0Gdm", - ["vcmpz.f32_1"] = "eeb50a40d", - ["vcmpz.f64_1"] = "eeb50b40Gd", - ["vcmpze.f32_1"] = "eeb50ac0d", - ["vcmpze.f64_1"] = "eeb50bc0Gd", - - vldr_2 = "ed100a00dl|ed100b00Gdl", - vstr_2 = "ed000a00dl|ed000b00Gdl", - vldm_2 = "ec900a00or", - vldmia_2 = "ec900a00or", - vldmdb_2 = "ed100a00or", - vpop_1 = "ecbd0a00r", - vstm_2 = "ec800a00or", - vstmia_2 = "ec800a00or", - vstmdb_2 = "ed000a00or", - vpush_1 = "ed2d0a00r", - - ["vmov.f32_2"] = "eeb00a40dm|eeb00a00dY", -- #imm is VFPv3 only - ["vmov.f64_2"] = "eeb00b40Gdm|eeb00b00GdY", -- #imm is VFPv3 only - vmov_2 = "ee100a10Dn|ee000a10nD", - vmov_3 = "ec500a10DNm|ec400a10mDN|ec500b10GDNm|ec400b10GmDN", - - vmrs_0 = "eef1fa10", - vmrs_1 = "eef10a10D", - vmsr_1 = "eee10a10D", - - ["vcvt.s32.f32_2"] = "eebd0ac0dm", - ["vcvt.s32.f64_2"] = "eebd0bc0dGm", - ["vcvt.u32.f32_2"] = "eebc0ac0dm", - ["vcvt.u32.f64_2"] = "eebc0bc0dGm", - ["vcvtr.s32.f32_2"] = "eebd0a40dm", - ["vcvtr.s32.f64_2"] = "eebd0b40dGm", - ["vcvtr.u32.f32_2"] = "eebc0a40dm", - ["vcvtr.u32.f64_2"] = "eebc0b40dGm", - ["vcvt.f32.s32_2"] = "eeb80ac0dm", - ["vcvt.f64.s32_2"] = "eeb80bc0GdFm", - ["vcvt.f32.u32_2"] = "eeb80a40dm", - ["vcvt.f64.u32_2"] = "eeb80b40GdFm", - ["vcvt.f32.f64_2"] = "eeb70bc0dGm", - ["vcvt.f64.f32_2"] = "eeb70ac0GdFm", - - -- VFPv4 only: - ["vfma.f32_3"] = "eea00a00dnm", - ["vfma.f64_3"] = "eea00b00Gdnm", - ["vfms.f32_3"] = "eea00a40dnm", - ["vfms.f64_3"] = "eea00b40Gdnm", - ["vfnma.f32_3"] = "ee900a40dnm", - ["vfnma.f64_3"] = "ee900b40Gdnm", - ["vfnms.f32_3"] = "ee900a00dnm", - ["vfnms.f64_3"] = "ee900b00Gdnm", - - -- NYI: Advanced SIMD instructions. - - -- NYI: I have no need for these instructions right now: - -- swp, swpb, strex, ldrex, strexd, ldrexd, strexb, ldrexb, strexh, ldrexh - -- msr, nopv6, yield, wfe, wfi, sev, dbg, bxj, smc, srs, rfe - -- cps, setend, pli, pld, pldw, clrex, dsb, dmb, isb - -- stc, ldc, mcr, mcr2, mrc, mrc2, mcrr, mcrr2, mrrc, mrrc2, cdp, cdp2 -} - --- Add mnemonics for "s" variants. -do - local t = {} - for k,v in pairs(map_op) do - if sub(v, -1) == "s" then - local v2 = sub(v, 1, 2)..char(byte(v, 3)+1)..sub(v, 4, -2) - t[sub(k, 1, -3).."s"..sub(k, -2)] = v2 - end - end - for k,v in pairs(t) do - map_op[k] = v - end -end - ------------------------------------------------------------------------------- - -local function parse_gpr(expr) - local tname, ovreg = match(expr, "^([%w_]+):(r1?[0-9])$") - local tp = map_type[tname or expr] - if tp then - local reg = ovreg or tp.reg - if not reg then - werror("type `"..(tname or expr).."' needs a register override") - end - expr = reg - end - local r = match(expr, "^r(1?[0-9])$") - if r then - r = tonumber(r) - if r <= 15 then return r, tp end - end - werror("bad register name `"..expr.."'") -end - -local function parse_gpr_pm(expr) - local pm, expr2 = match(expr, "^([+-]?)(.*)$") - return parse_gpr(expr2), (pm == "-") -end - -local function parse_vr(expr, tp) - local t, r = match(expr, "^([sd])([0-9]+)$") - if t == tp then - r = tonumber(r) - if r <= 31 then - if t == "s" then return shr(r, 1), band(r, 1) end - return band(r, 15), shr(r, 4) - end - end - werror("bad register name `"..expr.."'") -end - -local function parse_reglist(reglist) - reglist = match(reglist, "^{%s*([^}]*)}$") - if not reglist then werror("register list expected") end - local rr = 0 - for p in gmatch(reglist..",", "%s*([^,]*),") do - local rbit = shl(1, parse_gpr(gsub(p, "%s+$", ""))) - if band(rr, rbit) ~= 0 then - werror("duplicate register `"..p.."'") - end - rr = rr + rbit - end - return rr -end - -local function parse_vrlist(reglist) - local ta, ra, tb, rb = match(reglist, - "^{%s*([sd])([0-9]+)%s*%-%s*([sd])([0-9]+)%s*}$") - ra, rb = tonumber(ra), tonumber(rb) - if ta and ta == tb and ra and rb and ra <= 31 and rb <= 31 and ra <= rb then - local nr = rb+1 - ra - if ta == "s" then - return shl(shr(ra,1),12)+shl(band(ra,1),22) + nr - else - return shl(band(ra,15),12)+shl(shr(ra,4),22) + nr*2 + 0x100 - end - end - werror("register list expected") -end - -local function parse_imm(imm, bits, shift, scale, signed) - imm = match(imm, "^#(.*)$") - if not imm then werror("expected immediate operand") end - local n = tonumber(imm) - if n then - local m = sar(n, scale) - if shl(m, scale) == n then - if signed then - local s = sar(m, bits-1) - if s == 0 then return shl(m, shift) - elseif s == -1 then return shl(m + shl(1, bits), shift) end - else - if sar(m, bits) == 0 then return shl(m, shift) end - end - end - werror("out of range immediate `"..imm.."'") - else - waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm) - return 0 - end -end - -local function parse_imm12(imm) - local n = tonumber(imm) - if n then - local m = band(n) - for i=0,-15,-1 do - if shr(m, 8) == 0 then return m + shl(band(i, 15), 8) end - m = ror(m, 2) - end - werror("out of range immediate `"..imm.."'") - else - waction("IMM12", 0, imm) - return 0 - end -end - -local function parse_imm16(imm) - imm = match(imm, "^#(.*)$") - if not imm then werror("expected immediate operand") end - local n = tonumber(imm) - if n then - if shr(n, 16) == 0 then return band(n, 0x0fff) + shl(band(n, 0xf000), 4) end - werror("out of range immediate `"..imm.."'") - else - waction("IMM16", 32*16, imm) - return 0 - end -end - -local function parse_imm_load(imm, ext) - local n = tonumber(imm) - if n then - if ext then - if n >= -255 and n <= 255 then - local up = 0x00800000 - if n < 0 then n = -n; up = 0 end - return shl(band(n, 0xf0), 4) + band(n, 0x0f) + up - end - else - if n >= -4095 and n <= 4095 then - if n >= 0 then return n+0x00800000 end - return -n - end - end - werror("out of range immediate `"..imm.."'") - else - waction(ext and "IMML8" or "IMML12", 32768 + shl(ext and 8 or 12, 5), imm) - return 0 - end -end - -local function parse_shift(shift, gprok) - if shift == "rrx" then - return 3 * 32 - else - local s, s2 = match(shift, "^(%S+)%s*(.*)$") - s = map_shift[s] - if not s then werror("expected shift operand") end - if sub(s2, 1, 1) == "#" then - return parse_imm(s2, 5, 7, 0, false) + shl(s, 5) - else - if not gprok then werror("expected immediate shift operand") end - return shl(parse_gpr(s2), 8) + shl(s, 5) + 16 - end - end -end - -local function parse_label(label, def) - local prefix = sub(label, 1, 2) - -- =>label (pc label reference) - if prefix == "=>" then - return "PC", 0, sub(label, 3) - end - -- ->name (global label reference) - if prefix == "->" then - return "LG", map_global[sub(label, 3)] - end - if def then - -- [1-9] (local label definition) - if match(label, "^[1-9]$") then - return "LG", 10+tonumber(label) - end - else - -- [<>][1-9] (local label reference) - local dir, lnum = match(label, "^([<>])([1-9])$") - if dir then -- Fwd: 1-9, Bkwd: 11-19. - return "LG", lnum + (dir == ">" and 0 or 10) - end - -- extern label (extern label reference) - local extname = match(label, "^extern%s+(%S+)$") - if extname then - return "EXT", map_extern[extname] - end - end - werror("bad label `"..label.."'") -end - -local function parse_load(params, nparams, n, op) - local oplo = band(op, 255) - local ext, ldrd = (oplo ~= 0), (oplo == 208) - local d - if (ldrd or oplo == 240) then - d = band(shr(op, 12), 15) - if band(d, 1) ~= 0 then werror("odd destination register") end - end - local pn = params[n] - local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") - local p2 = params[n+1] - if not p1 then - if not p2 then - if match(pn, "^[<>=%-]") or match(pn, "^extern%s+") then - local mode, n, s = parse_label(pn, false) - waction("REL_"..mode, n + (ext and 0x1800 or 0x0800), s, 1) - return op + 15 * 65536 + 0x01000000 + (ext and 0x00400000 or 0) - end - local reg, tailr = match(pn, "^([%w_:]+)%s*(.*)$") - if reg and tailr ~= "" then - local d, tp = parse_gpr(reg) - if tp then - waction(ext and "IMML8" or "IMML12", 32768 + 32*(ext and 8 or 12), - format(tp.ctypefmt, tailr)) - return op + shl(d, 16) + 0x01000000 + (ext and 0x00400000 or 0) - end - end - end - werror("expected address operand") - end - if wb == "!" then op = op + 0x00200000 end - if p2 then - if wb == "!" then werror("bad use of '!'") end - local p3 = params[n+2] - op = op + shl(parse_gpr(p1), 16) - local imm = match(p2, "^#(.*)$") - if imm then - local m = parse_imm_load(imm, ext) - if p3 then werror("too many parameters") end - op = op + m + (ext and 0x00400000 or 0) - else - local m, neg = parse_gpr_pm(p2) - if ldrd and (m == d or m-1 == d) then werror("register conflict") end - op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000) - if p3 then op = op + parse_shift(p3) end - end - else - local p1a, p2 = match(p1, "^([^,%s]*)%s*(.*)$") - op = op + shl(parse_gpr(p1a), 16) + 0x01000000 - if p2 ~= "" then - local imm = match(p2, "^,%s*#(.*)$") - if imm then - local m = parse_imm_load(imm, ext) - op = op + m + (ext and 0x00400000 or 0) - else - local p2a, p3 = match(p2, "^,%s*([^,%s]*)%s*,?%s*(.*)$") - local m, neg = parse_gpr_pm(p2a) - if ldrd and (m == d or m-1 == d) then werror("register conflict") end - op = op + m + (neg and 0 or 0x00800000) + (ext and 0 or 0x02000000) - if p3 ~= "" then - if ext then werror("too many parameters") end - op = op + parse_shift(p3) - end - end - else - if wb == "!" then werror("bad use of '!'") end - op = op + (ext and 0x00c00000 or 0x00800000) - end - end - return op -end - -local function parse_vload(q) - local reg, imm = match(q, "^%[%s*([^,%s]*)%s*(.*)%]$") - if reg then - local d = shl(parse_gpr(reg), 16) - if imm == "" then return d end - imm = match(imm, "^,%s*#(.*)$") - if imm then - local n = tonumber(imm) - if n then - if n >= -1020 and n <= 1020 and n%4 == 0 then - return d + (n >= 0 and n/4+0x00800000 or -n/4) - end - werror("out of range immediate `"..imm.."'") - else - waction("IMMV8", 32768 + 32*8, imm) - return d - end - end - else - if match(q, "^[<>=%-]") or match(q, "^extern%s+") then - local mode, n, s = parse_label(q, false) - waction("REL_"..mode, n + 0x2800, s, 1) - return 15 * 65536 - end - local reg, tailr = match(q, "^([%w_:]+)%s*(.*)$") - if reg and tailr ~= "" then - local d, tp = parse_gpr(reg) - if tp then - waction("IMMV8", 32768 + 32*8, format(tp.ctypefmt, tailr)) - return shl(d, 16) - end - end - end - werror("expected address operand") -end - ------------------------------------------------------------------------------- - --- Handle opcodes defined with template strings. -local function parse_template(params, template, nparams, pos) - local op = tonumber(sub(template, 1, 8), 16) - local n = 1 - local vr = "s" - - -- Process each character. - for p in gmatch(sub(template, 9), ".") do - local q = params[n] - if p == "D" then - op = op + shl(parse_gpr(q), 12); n = n + 1 - elseif p == "N" then - op = op + shl(parse_gpr(q), 16); n = n + 1 - elseif p == "S" then - op = op + shl(parse_gpr(q), 8); n = n + 1 - elseif p == "M" then - op = op + parse_gpr(q); n = n + 1 - elseif p == "d" then - local r,h = parse_vr(q, vr); op = op+shl(r,12)+shl(h,22); n = n + 1 - elseif p == "n" then - local r,h = parse_vr(q, vr); op = op+shl(r,16)+shl(h,7); n = n + 1 - elseif p == "m" then - local r,h = parse_vr(q, vr); op = op+r+shl(h,5); n = n + 1 - elseif p == "P" then - local imm = match(q, "^#(.*)$") - if imm then - op = op + parse_imm12(imm) + 0x02000000 - else - op = op + parse_gpr(q) - end - n = n + 1 - elseif p == "p" then - op = op + parse_shift(q, true); n = n + 1 - elseif p == "L" then - op = parse_load(params, nparams, n, op) - elseif p == "l" then - op = op + parse_vload(q) - elseif p == "B" then - local mode, n, s = parse_label(q, false) - waction("REL_"..mode, n, s, 1) - elseif p == "C" then -- blx gpr vs. blx label. - if match(q, "^([%w_]+):(r1?[0-9])$") or match(q, "^r(1?[0-9])$") then - op = op + parse_gpr(q) - else - if op < 0xe0000000 then werror("unconditional instruction") end - local mode, n, s = parse_label(q, false) - waction("REL_"..mode, n, s, 1) - op = 0xfa000000 - end - elseif p == "F" then - vr = "s" - elseif p == "G" then - vr = "d" - elseif p == "o" then - local r, wb = match(q, "^([^!]*)(!?)$") - op = op + shl(parse_gpr(r), 16) + (wb == "!" and 0x00200000 or 0) - n = n + 1 - elseif p == "R" then - op = op + parse_reglist(q); n = n + 1 - elseif p == "r" then - op = op + parse_vrlist(q); n = n + 1 - elseif p == "W" then - op = op + parse_imm16(q); n = n + 1 - elseif p == "v" then - op = op + parse_imm(q, 5, 7, 0, false); n = n + 1 - elseif p == "w" then - local imm = match(q, "^#(.*)$") - if imm then - op = op + parse_imm(q, 5, 7, 0, false); n = n + 1 - else - op = op + shl(parse_gpr(q), 8) + 16 - end - elseif p == "X" then - op = op + parse_imm(q, 5, 16, 0, false); n = n + 1 - elseif p == "Y" then - local imm = tonumber(match(q, "^#(.*)$")); n = n + 1 - if not imm or shr(imm, 8) ~= 0 then - werror("bad immediate operand") - end - op = op + shl(band(imm, 0xf0), 12) + band(imm, 0x0f) - elseif p == "K" then - local imm = tonumber(match(q, "^#(.*)$")); n = n + 1 - if not imm or shr(imm, 16) ~= 0 then - werror("bad immediate operand") - end - op = op + shl(band(imm, 0xfff0), 4) + band(imm, 0x000f) - elseif p == "T" then - op = op + parse_imm(q, 24, 0, 0, false); n = n + 1 - elseif p == "s" then - -- Ignored. - else - assert(false) - end - end - wputpos(pos, op) -end - -map_op[".template__"] = function(params, template, nparams) - if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end - - -- Limit number of section buffer positions used by a single dasm_put(). - -- A single opcode needs a maximum of 3 positions. - if secpos+3 > maxsecpos then wflush() end - local pos = wpos() - local lpos, apos, spos = #actlist, #actargs, secpos - - local ok, err - for t in gmatch(template, "[^|]+") do - ok, err = pcall(parse_template, params, t, nparams, pos) - if ok then return end - secpos = spos - actlist[lpos+1] = nil - actlist[lpos+2] = nil - actlist[lpos+3] = nil - actargs[apos+1] = nil - actargs[apos+2] = nil - actargs[apos+3] = nil - end - error(err, 0) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode to mark the position where the action list is to be emitted. -map_op[".actionlist_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeactions(out, name) end) -end - --- Pseudo-opcode to mark the position where the global enum is to be emitted. -map_op[".globals_1"] = function(params) - if not params then return "prefix" end - local prefix = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobals(out, prefix) end) -end - --- Pseudo-opcode to mark the position where the global names are to be emitted. -map_op[".globalnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobalnames(out, name) end) -end - --- Pseudo-opcode to mark the position where the extern names are to be emitted. -map_op[".externnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeexternnames(out, name) end) -end - ------------------------------------------------------------------------------- - --- Label pseudo-opcode (converted from trailing colon form). -map_op[".label_1"] = function(params) - if not params then return "[1-9] | ->global | =>pcexpr" end - if secpos+1 > maxsecpos then wflush() end - local mode, n, s = parse_label(params[1], true) - if mode == "EXT" then werror("bad label definition") end - waction("LABEL_"..mode, n, s, 1) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcodes for data storage. -map_op[".long_*"] = function(params) - if not params then return "imm..." end - for _,p in ipairs(params) do - local n = tonumber(p) - if not n then werror("bad immediate `"..p.."'") end - if n < 0 then n = n + 2^32 end - wputw(n) - if secpos+2 > maxsecpos then wflush() end - end -end - --- Alignment pseudo-opcode. -map_op[".align_1"] = function(params) - if not params then return "numpow2" end - if secpos+1 > maxsecpos then wflush() end - local align = tonumber(params[1]) - if align then - local x = align - -- Must be a power of 2 in the range (2 ... 256). - for i=1,8 do - x = x / 2 - if x == 1 then - waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. - return - end - end - end - werror("bad alignment") -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode for (primitive) type definitions (map to C types). -map_op[".type_3"] = function(params, nparams) - if not params then - return nparams == 2 and "name, ctype" or "name, ctype, reg" - end - local name, ctype, reg = params[1], params[2], params[3] - if not match(name, "^[%a_][%w_]*$") then - werror("bad type name `"..name.."'") - end - local tp = map_type[name] - if tp then - werror("duplicate type `"..name.."'") - end - -- Add #type to defines. A bit unclean to put it in map_archdef. - map_archdef["#"..name] = "sizeof("..ctype..")" - -- Add new type and emit shortcut define. - local num = ctypenum + 1 - map_type[name] = { - ctype = ctype, - ctypefmt = format("Dt%X(%%s)", num), - reg = reg, - } - wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) - ctypenum = num -end -map_op[".type_2"] = map_op[".type_3"] - --- Dump type definitions. -local function dumptypes(out, lvl) - local t = {} - for name in pairs(map_type) do t[#t+1] = name end - sort(t) - out:write("Type definitions:\n") - for _,name in ipairs(t) do - local tp = map_type[name] - local reg = tp.reg or "" - out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Set the current section. -function _M.section(num) - waction("SECTION", num) - wflush(true) -- SECTION is a terminal action. -end - ------------------------------------------------------------------------------- - --- Dump architecture description. -function _M.dumparch(out) - out:write(format("DynASM %s version %s, released %s\n\n", - _info.arch, _info.version, _info.release)) - dumpactions(out) -end - --- Dump all user defined elements. -function _M.dumpdef(out, lvl) - dumptypes(out, lvl) - dumpglobals(out, lvl) - dumpexterns(out, lvl) -end - ------------------------------------------------------------------------------- - --- Pass callbacks from/to the DynASM core. -function _M.passcb(wl, we, wf, ww) - wline, werror, wfatal, wwarn = wl, we, wf, ww - return wflush -end - --- Setup the arch-specific module. -function _M.setup(arch, opt) - g_arch, g_opt = arch, opt -end - --- Merge the core maps and the arch-specific maps. -function _M.mergemaps(map_coreop, map_def) - setmetatable(map_op, { __index = function(t, k) - local v = map_coreop[k] - if v then return v end - local k1, cc, k2 = match(k, "^(.-)(..)([._].*)$") - local cv = map_cond[cc] - if cv then - local v = rawget(t, k1..k2) - if type(v) == "string" then - local scv = format("%x", cv) - return gsub(scv..sub(v, 2), "|e", "|"..scv) - end - end - end }) - setmetatable(map_def, { __index = map_archdef }) - return map_op, map_def -end - -return _M - ------------------------------------------------------------------------------- - diff --git a/core/src/luajit/dynasm/dasm_mips.h b/core/src/luajit/dynasm/dasm_mips.h deleted file mode 100644 index 2f4c2d222..000000000 --- a/core/src/luajit/dynasm/dasm_mips.h +++ /dev/null @@ -1,416 +0,0 @@ -/* -** DynASM MIPS encoding engine. -** Copyright (C) 2005-2015 Mike Pall. All rights reserved. -** Released under the MIT license. See dynasm.lua for full copyright notice. -*/ - -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> - -#define DASM_ARCH "mips" - -#ifndef DASM_EXTERN -#define DASM_EXTERN(a,b,c,d) 0 -#endif - -/* Action definitions. */ -enum { - DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT, - /* The following actions need a buffer position. */ - DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, - /* The following actions also have an argument. */ - DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, - DASM__MAX -}; - -/* Maximum number of section buffer positions for a single dasm_put() call. */ -#define DASM_MAXSECPOS 25 - -/* DynASM encoder status codes. Action list offset or number are or'ed in. */ -#define DASM_S_OK 0x00000000 -#define DASM_S_NOMEM 0x01000000 -#define DASM_S_PHASE 0x02000000 -#define DASM_S_MATCH_SEC 0x03000000 -#define DASM_S_RANGE_I 0x11000000 -#define DASM_S_RANGE_SEC 0x12000000 -#define DASM_S_RANGE_LG 0x13000000 -#define DASM_S_RANGE_PC 0x14000000 -#define DASM_S_RANGE_REL 0x15000000 -#define DASM_S_UNDEF_LG 0x21000000 -#define DASM_S_UNDEF_PC 0x22000000 - -/* Macros to convert positions (8 bit section + 24 bit index). */ -#define DASM_POS2IDX(pos) ((pos)&0x00ffffff) -#define DASM_POS2BIAS(pos) ((pos)&0xff000000) -#define DASM_SEC2POS(sec) ((sec)<<24) -#define DASM_POS2SEC(pos) ((pos)>>24) -#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) - -/* Action list type. */ -typedef const unsigned int *dasm_ActList; - -/* Per-section structure. */ -typedef struct dasm_Section { - int *rbuf; /* Biased buffer pointer (negative section bias). */ - int *buf; /* True buffer pointer. */ - size_t bsize; /* Buffer size in bytes. */ - int pos; /* Biased buffer position. */ - int epos; /* End of biased buffer position - max single put. */ - int ofs; /* Byte offset into section. */ -} dasm_Section; - -/* Core structure holding the DynASM encoding state. */ -struct dasm_State { - size_t psize; /* Allocated size of this structure. */ - dasm_ActList actionlist; /* Current actionlist pointer. */ - int *lglabels; /* Local/global chain/pos ptrs. */ - size_t lgsize; - int *pclabels; /* PC label chains/pos ptrs. */ - size_t pcsize; - void **globals; /* Array of globals (bias -10). */ - dasm_Section *section; /* Pointer to active section. */ - size_t codesize; /* Total size of all code sections. */ - int maxsection; /* 0 <= sectionidx < maxsection. */ - int status; /* Status code. */ - dasm_Section sections[1]; /* All sections. Alloc-extended. */ -}; - -/* The size of the core structure depends on the max. number of sections. */ -#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) - - -/* Initialize DynASM state. */ -void dasm_init(Dst_DECL, int maxsection) -{ - dasm_State *D; - size_t psz = 0; - int i; - Dst_REF = NULL; - DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); - D = Dst_REF; - D->psize = psz; - D->lglabels = NULL; - D->lgsize = 0; - D->pclabels = NULL; - D->pcsize = 0; - D->globals = NULL; - D->maxsection = maxsection; - for (i = 0; i < maxsection; i++) { - D->sections[i].buf = NULL; /* Need this for pass3. */ - D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); - D->sections[i].bsize = 0; - D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ - } -} - -/* Free DynASM state. */ -void dasm_free(Dst_DECL) -{ - dasm_State *D = Dst_REF; - int i; - for (i = 0; i < D->maxsection; i++) - if (D->sections[i].buf) - DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); - if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); - if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); - DASM_M_FREE(Dst, D, D->psize); -} - -/* Setup global label array. Must be called before dasm_setup(). */ -void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) -{ - dasm_State *D = Dst_REF; - D->globals = gl - 10; /* Negative bias to compensate for locals. */ - DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); -} - -/* Grow PC label array. Can be called after dasm_setup(), too. */ -void dasm_growpc(Dst_DECL, unsigned int maxpc) -{ - dasm_State *D = Dst_REF; - size_t osz = D->pcsize; - DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); - memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); -} - -/* Setup encoder. */ -void dasm_setup(Dst_DECL, const void *actionlist) -{ - dasm_State *D = Dst_REF; - int i; - D->actionlist = (dasm_ActList)actionlist; - D->status = DASM_S_OK; - D->section = &D->sections[0]; - memset((void *)D->lglabels, 0, D->lgsize); - if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); - for (i = 0; i < D->maxsection; i++) { - D->sections[i].pos = DASM_SEC2POS(i); - D->sections[i].ofs = 0; - } -} - - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) { \ - D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0) -#define CKPL(kind, st) \ - do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ - D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0) -#else -#define CK(x, st) ((void)0) -#define CKPL(kind, st) ((void)0) -#endif - -/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ -void dasm_put(Dst_DECL, int start, ...) -{ - va_list ap; - dasm_State *D = Dst_REF; - dasm_ActList p = D->actionlist + start; - dasm_Section *sec = D->section; - int pos = sec->pos, ofs = sec->ofs; - int *b; - - if (pos >= sec->epos) { - DASM_M_GROW(Dst, int, sec->buf, sec->bsize, - sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); - sec->rbuf = sec->buf - DASM_POS2BIAS(pos); - sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); - } - - b = sec->rbuf; - b[pos++] = start; - - va_start(ap, start); - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16) - 0xff00; - if (action >= DASM__MAX) { - ofs += 4; - } else { - int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0; - switch (action) { - case DASM_STOP: goto stop; - case DASM_SECTION: - n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); - D->section = &D->sections[n]; goto stop; - case DASM_ESC: p++; ofs += 4; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; - case DASM_REL_LG: - n = (ins & 2047) - 10; pl = D->lglabels + n; - /* Bkwd rel or global. */ - if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; } - pl += 10; n = *pl; - if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ - goto linkrel; - case DASM_REL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putrel: - n = *pl; - if (n < 0) { /* Label exists. Get label pos and store it. */ - b[pos] = -n; - } else { - linkrel: - b[pos] = n; /* Else link to rel chain, anchored at label. */ - *pl = pos; - } - pos++; - break; - case DASM_LABEL_LG: - pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; - case DASM_LABEL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putlabel: - n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; - } - *pl = -pos; /* Label exists now. */ - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_IMM: -#ifdef DASM_CHECKS - CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); -#endif - n >>= ((ins>>10)&31); -#ifdef DASM_CHECKS - if (ins & 0x8000) - CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I); - else - CK((n>>((ins>>5)&31)) == 0, RANGE_I); -#endif - b[pos++] = n; - break; - } - } - } -stop: - va_end(ap); - sec->pos = pos; - sec->ofs = ofs; -} -#undef CK - -/* Pass 2: Link sections, shrink aligns, fix label offsets. */ -int dasm_link(Dst_DECL, size_t *szp) -{ - dasm_State *D = Dst_REF; - int secnum; - int ofs = 0; - -#ifdef DASM_CHECKS - *szp = 0; - if (D->status != DASM_S_OK) return D->status; - { - int pc; - for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) - if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; - } -#endif - - { /* Handle globals not defined in this translation unit. */ - int idx; - for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { - int n = D->lglabels[idx]; - /* Undefined label: Collapse rel chain and replace with marker (< 0). */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } - } - } - - /* Combine all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->rbuf; - int pos = DASM_SEC2POS(secnum); - int lastpos = sec->pos; - - while (pos != lastpos) { - dasm_ActList p = D->actionlist + b[pos++]; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16) - 0xff00; - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: p++; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; - case DASM_REL_LG: case DASM_REL_PC: pos++; break; - case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; - case DASM_IMM: pos++; break; - } - } - stop: (void)0; - } - ofs += sec->ofs; /* Next section starts right after current section. */ - } - - D->codesize = ofs; /* Total size of all code sections */ - *szp = ofs; - return DASM_S_OK; -} - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0) -#else -#define CK(x, st) ((void)0) -#endif - -/* Pass 3: Encode sections. */ -int dasm_encode(Dst_DECL, void *buffer) -{ - dasm_State *D = Dst_REF; - char *base = (char *)buffer; - unsigned int *cp = (unsigned int *)buffer; - int secnum; - - /* Encode all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->buf; - int *endb = sec->rbuf + sec->pos; - - while (b != endb) { - dasm_ActList p = D->actionlist + *b++; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16) - 0xff00; - int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0; - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: *cp++ = *p++; break; - case DASM_REL_EXT: - n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1); - goto patchrel; - case DASM_ALIGN: - ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; - break; - case DASM_REL_LG: - CK(n >= 0, UNDEF_LG); - case DASM_REL_PC: - CK(n >= 0, UNDEF_PC); - n = *DASM_POS2PTR(D, n); - if (ins & 2048) - n = n - (int)((char *)cp - base); - else - n = (n + (int)base) & 0x0fffffff; - patchrel: - CK((n & 3) == 0 && - ((n + ((ins & 2048) ? 0x00020000 : 0)) >> - ((ins & 2048) ? 18 : 28)) == 0, RANGE_REL); - cp[-1] |= ((n>>2) & ((ins & 2048) ? 0x0000ffff: 0x03ffffff)); - break; - case DASM_LABEL_LG: - ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); - break; - case DASM_LABEL_PC: break; - case DASM_IMM: - cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); - break; - default: *cp++ = ins; break; - } - } - stop: (void)0; - } - } - - if (base + D->codesize != (char *)cp) /* Check for phase errors. */ - return DASM_S_PHASE; - return DASM_S_OK; -} -#undef CK - -/* Get PC label offset. */ -int dasm_getpclabel(Dst_DECL, unsigned int pc) -{ - dasm_State *D = Dst_REF; - if (pc*sizeof(int) < D->pcsize) { - int pos = D->pclabels[pc]; - if (pos < 0) return *DASM_POS2PTR(D, -pos); - if (pos > 0) return -1; /* Undefined. */ - } - return -2; /* Unused or out of range. */ -} - -#ifdef DASM_CHECKS -/* Optional sanity checker to call between isolated encoding steps. */ -int dasm_checkstep(Dst_DECL, int secmatch) -{ - dasm_State *D = Dst_REF; - if (D->status == DASM_S_OK) { - int i; - for (i = 1; i <= 9; i++) { - if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; } - D->lglabels[i] = 0; - } - } - if (D->status == DASM_S_OK && secmatch >= 0 && - D->section != &D->sections[secmatch]) - D->status = DASM_S_MATCH_SEC|(D->section-D->sections); - return D->status; -} -#endif - diff --git a/core/src/luajit/dynasm/dasm_mips.lua b/core/src/luajit/dynasm/dasm_mips.lua deleted file mode 100644 index ae0dbd7a9..000000000 --- a/core/src/luajit/dynasm/dasm_mips.lua +++ /dev/null @@ -1,953 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM MIPS module. --- --- Copyright (C) 2005-2015 Mike Pall. All rights reserved. --- See dynasm.lua for full copyright notice. ------------------------------------------------------------------------------- - --- Module information: -local _info = { - arch = "mips", - description = "DynASM MIPS module", - version = "1.3.0", - vernum = 10300, - release = "2012-01-23", - author = "Mike Pall", - license = "MIT", -} - --- Exported glue functions for the arch-specific module. -local _M = { _info = _info } - --- Cache library functions. -local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs -local assert, setmetatable = assert, setmetatable -local _s = string -local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char -local match, gmatch = _s.match, _s.gmatch -local concat, sort = table.concat, table.sort -local bit = bit or require("bit") -local band, shl, sar, tohex = bit.band, bit.lshift, bit.arshift, bit.tohex - --- Inherited tables and callbacks. -local g_opt, g_arch -local wline, werror, wfatal, wwarn - --- Action name list. --- CHECK: Keep this in sync with the C code! -local action_names = { - "STOP", "SECTION", "ESC", "REL_EXT", - "ALIGN", "REL_LG", "LABEL_LG", - "REL_PC", "LABEL_PC", "IMM", -} - --- Maximum number of section buffer positions for dasm_put(). --- CHECK: Keep this in sync with the C code! -local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. - --- Action name -> action number. -local map_action = {} -for n,name in ipairs(action_names) do - map_action[name] = n-1 -end - --- Action list buffer. -local actlist = {} - --- Argument list for next dasm_put(). Start with offset 0 into action list. -local actargs = { 0 } - --- Current number of section buffer positions for dasm_put(). -local secpos = 1 - ------------------------------------------------------------------------------- - --- Dump action names and numbers. -local function dumpactions(out) - out:write("DynASM encoding engine action codes:\n") - for n,name in ipairs(action_names) do - local num = map_action[name] - out:write(format(" %-10s %02X %d\n", name, num, num)) - end - out:write("\n") -end - --- Write action list buffer as a huge static C array. -local function writeactions(out, name) - local nn = #actlist - if nn == 0 then nn = 1; actlist[0] = map_action.STOP end - out:write("static const unsigned int ", name, "[", nn, "] = {\n") - for i = 1,nn-1 do - assert(out:write("0x", tohex(actlist[i]), ",\n")) - end - assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) -end - ------------------------------------------------------------------------------- - --- Add word to action list. -local function wputxw(n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - actlist[#actlist+1] = n -end - --- Add action to list with optional arg. Advance buffer pos, too. -local function waction(action, val, a, num) - local w = assert(map_action[action], "bad action name `"..action.."'") - wputxw(0xff000000 + w * 0x10000 + (val or 0)) - if a then actargs[#actargs+1] = a end - if a or num then secpos = secpos + (num or 1) end -end - --- Flush action list (intervening C code or buffer pos overflow). -local function wflush(term) - if #actlist == actargs[1] then return end -- Nothing to flush. - if not term then waction("STOP") end -- Terminate action list. - wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) - actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). - secpos = 1 -- The actionlist offset occupies a buffer position, too. -end - --- Put escaped word. -local function wputw(n) - if n >= 0xff000000 then waction("ESC") end - wputxw(n) -end - --- Reserve position for word. -local function wpos() - local pos = #actlist+1 - actlist[pos] = "" - return pos -end - --- Store word to reserved position. -local function wputpos(pos, n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - actlist[pos] = n -end - ------------------------------------------------------------------------------- - --- Global label name -> global label number. With auto assignment on 1st use. -local next_global = 20 -local map_global = setmetatable({}, { __index = function(t, name) - if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end - local n = next_global - if n > 2047 then werror("too many global labels") end - next_global = n + 1 - t[name] = n - return n -end}) - --- Dump global labels. -local function dumpglobals(out, lvl) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("Global labels:\n") - for i=20,next_global-1 do - out:write(format(" %s\n", t[i])) - end - out:write("\n") -end - --- Write global label enum. -local function writeglobals(out, prefix) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("enum {\n") - for i=20,next_global-1 do - out:write(" ", prefix, t[i], ",\n") - end - out:write(" ", prefix, "_MAX\n};\n") -end - --- Write global label names. -local function writeglobalnames(out, name) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("static const char *const ", name, "[] = {\n") - for i=20,next_global-1 do - out:write(" \"", t[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Extern label name -> extern label number. With auto assignment on 1st use. -local next_extern = 0 -local map_extern_ = {} -local map_extern = setmetatable({}, { __index = function(t, name) - -- No restrictions on the name for now. - local n = next_extern - if n > 2047 then werror("too many extern labels") end - next_extern = n + 1 - t[name] = n - map_extern_[n] = name - return n -end}) - --- Dump extern labels. -local function dumpexterns(out, lvl) - out:write("Extern labels:\n") - for i=0,next_extern-1 do - out:write(format(" %s\n", map_extern_[i])) - end - out:write("\n") -end - --- Write extern label names. -local function writeexternnames(out, name) - out:write("static const char *const ", name, "[] = {\n") - for i=0,next_extern-1 do - out:write(" \"", map_extern_[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Arch-specific maps. -local map_archdef = { sp="r29", ra="r31" } -- Ext. register name -> int. name. - -local map_type = {} -- Type name -> { ctype, reg } -local ctypenum = 0 -- Type number (for Dt... macros). - --- Reverse defines for registers. -function _M.revdef(s) - if s == "r29" then return "sp" - elseif s == "r31" then return "ra" end - return s -end - ------------------------------------------------------------------------------- - --- Template strings for MIPS instructions. -local map_op = { - -- First-level opcodes. - j_1 = "08000000J", - jal_1 = "0c000000J", - b_1 = "10000000B", - beqz_2 = "10000000SB", - beq_3 = "10000000STB", - bnez_2 = "14000000SB", - bne_3 = "14000000STB", - blez_2 = "18000000SB", - bgtz_2 = "1c000000SB", - addi_3 = "20000000TSI", - li_2 = "24000000TI", - addiu_3 = "24000000TSI", - slti_3 = "28000000TSI", - sltiu_3 = "2c000000TSI", - andi_3 = "30000000TSU", - lu_2 = "34000000TU", - ori_3 = "34000000TSU", - xori_3 = "38000000TSU", - lui_2 = "3c000000TU", - beqzl_2 = "50000000SB", - beql_3 = "50000000STB", - bnezl_2 = "54000000SB", - bnel_3 = "54000000STB", - blezl_2 = "58000000SB", - bgtzl_2 = "5c000000SB", - lb_2 = "80000000TO", - lh_2 = "84000000TO", - lwl_2 = "88000000TO", - lw_2 = "8c000000TO", - lbu_2 = "90000000TO", - lhu_2 = "94000000TO", - lwr_2 = "98000000TO", - sb_2 = "a0000000TO", - sh_2 = "a4000000TO", - swl_2 = "a8000000TO", - sw_2 = "ac000000TO", - swr_2 = "b8000000TO", - cache_2 = "bc000000NO", - ll_2 = "c0000000TO", - lwc1_2 = "c4000000HO", - pref_2 = "cc000000NO", - ldc1_2 = "d4000000HO", - sc_2 = "e0000000TO", - swc1_2 = "e4000000HO", - sdc1_2 = "f4000000HO", - - -- Opcode SPECIAL. - nop_0 = "00000000", - sll_3 = "00000000DTA", - movf_2 = "00000001DS", - movf_3 = "00000001DSC", - movt_2 = "00010001DS", - movt_3 = "00010001DSC", - srl_3 = "00000002DTA", - rotr_3 = "00200002DTA", - sra_3 = "00000003DTA", - sllv_3 = "00000004DTS", - srlv_3 = "00000006DTS", - rotrv_3 = "00000046DTS", - srav_3 = "00000007DTS", - jr_1 = "00000008S", - jalr_1 = "0000f809S", - jalr_2 = "00000009DS", - movz_3 = "0000000aDST", - movn_3 = "0000000bDST", - syscall_0 = "0000000c", - syscall_1 = "0000000cY", - break_0 = "0000000d", - break_1 = "0000000dY", - sync_0 = "0000000f", - mfhi_1 = "00000010D", - mthi_1 = "00000011S", - mflo_1 = "00000012D", - mtlo_1 = "00000013S", - mult_2 = "00000018ST", - multu_2 = "00000019ST", - div_2 = "0000001aST", - divu_2 = "0000001bST", - add_3 = "00000020DST", - move_2 = "00000021DS", - addu_3 = "00000021DST", - sub_3 = "00000022DST", - negu_2 = "00000023DT", - subu_3 = "00000023DST", - and_3 = "00000024DST", - or_3 = "00000025DST", - xor_3 = "00000026DST", - not_2 = "00000027DS", - nor_3 = "00000027DST", - slt_3 = "0000002aDST", - sltu_3 = "0000002bDST", - tge_2 = "00000030ST", - tge_3 = "00000030STZ", - tgeu_2 = "00000031ST", - tgeu_3 = "00000031STZ", - tlt_2 = "00000032ST", - tlt_3 = "00000032STZ", - tltu_2 = "00000033ST", - tltu_3 = "00000033STZ", - teq_2 = "00000034ST", - teq_3 = "00000034STZ", - tne_2 = "00000036ST", - tne_3 = "00000036STZ", - - -- Opcode REGIMM. - bltz_2 = "04000000SB", - bgez_2 = "04010000SB", - bltzl_2 = "04020000SB", - bgezl_2 = "04030000SB", - tgei_2 = "04080000SI", - tgeiu_2 = "04090000SI", - tlti_2 = "040a0000SI", - tltiu_2 = "040b0000SI", - teqi_2 = "040c0000SI", - tnei_2 = "040e0000SI", - bltzal_2 = "04100000SB", - bal_1 = "04110000B", - bgezal_2 = "04110000SB", - bltzall_2 = "04120000SB", - bgezall_2 = "04130000SB", - synci_1 = "041f0000O", - - -- Opcode SPECIAL2. - madd_2 = "70000000ST", - maddu_2 = "70000001ST", - mul_3 = "70000002DST", - msub_2 = "70000004ST", - msubu_2 = "70000005ST", - clz_2 = "70000020DS=", - clo_2 = "70000021DS=", - sdbbp_0 = "7000003f", - sdbbp_1 = "7000003fY", - - -- Opcode SPECIAL3. - ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1 - ins_4 = "7c000004TSAM", -- Note: last arg is msb = pos+size-1 - wsbh_2 = "7c0000a0DT", - seb_2 = "7c000420DT", - seh_2 = "7c000620DT", - rdhwr_2 = "7c00003bTD", - - -- Opcode COP0. - mfc0_2 = "40000000TD", - mfc0_3 = "40000000TDW", - mtc0_2 = "40800000TD", - mtc0_3 = "40800000TDW", - rdpgpr_2 = "41400000DT", - di_0 = "41606000", - di_1 = "41606000T", - ei_0 = "41606020", - ei_1 = "41606020T", - wrpgpr_2 = "41c00000DT", - tlbr_0 = "42000001", - tlbwi_0 = "42000002", - tlbwr_0 = "42000006", - tlbp_0 = "42000008", - eret_0 = "42000018", - deret_0 = "4200001f", - wait_0 = "42000020", - - -- Opcode COP1. - mfc1_2 = "44000000TG", - cfc1_2 = "44400000TG", - mfhc1_2 = "44600000TG", - mtc1_2 = "44800000TG", - ctc1_2 = "44c00000TG", - mthc1_2 = "44e00000TG", - - bc1f_1 = "45000000B", - bc1f_2 = "45000000CB", - bc1t_1 = "45010000B", - bc1t_2 = "45010000CB", - bc1fl_1 = "45020000B", - bc1fl_2 = "45020000CB", - bc1tl_1 = "45030000B", - bc1tl_2 = "45030000CB", - - ["add.s_3"] = "46000000FGH", - ["sub.s_3"] = "46000001FGH", - ["mul.s_3"] = "46000002FGH", - ["div.s_3"] = "46000003FGH", - ["sqrt.s_2"] = "46000004FG", - ["abs.s_2"] = "46000005FG", - ["mov.s_2"] = "46000006FG", - ["neg.s_2"] = "46000007FG", - ["round.l.s_2"] = "46000008FG", - ["trunc.l.s_2"] = "46000009FG", - ["ceil.l.s_2"] = "4600000aFG", - ["floor.l.s_2"] = "4600000bFG", - ["round.w.s_2"] = "4600000cFG", - ["trunc.w.s_2"] = "4600000dFG", - ["ceil.w.s_2"] = "4600000eFG", - ["floor.w.s_2"] = "4600000fFG", - ["movf.s_2"] = "46000011FG", - ["movf.s_3"] = "46000011FGC", - ["movt.s_2"] = "46010011FG", - ["movt.s_3"] = "46010011FGC", - ["movz.s_3"] = "46000012FGT", - ["movn.s_3"] = "46000013FGT", - ["recip.s_2"] = "46000015FG", - ["rsqrt.s_2"] = "46000016FG", - ["cvt.d.s_2"] = "46000021FG", - ["cvt.w.s_2"] = "46000024FG", - ["cvt.l.s_2"] = "46000025FG", - ["cvt.ps.s_3"] = "46000026FGH", - ["c.f.s_2"] = "46000030GH", - ["c.f.s_3"] = "46000030VGH", - ["c.un.s_2"] = "46000031GH", - ["c.un.s_3"] = "46000031VGH", - ["c.eq.s_2"] = "46000032GH", - ["c.eq.s_3"] = "46000032VGH", - ["c.ueq.s_2"] = "46000033GH", - ["c.ueq.s_3"] = "46000033VGH", - ["c.olt.s_2"] = "46000034GH", - ["c.olt.s_3"] = "46000034VGH", - ["c.ult.s_2"] = "46000035GH", - ["c.ult.s_3"] = "46000035VGH", - ["c.ole.s_2"] = "46000036GH", - ["c.ole.s_3"] = "46000036VGH", - ["c.ule.s_2"] = "46000037GH", - ["c.ule.s_3"] = "46000037VGH", - ["c.sf.s_2"] = "46000038GH", - ["c.sf.s_3"] = "46000038VGH", - ["c.ngle.s_2"] = "46000039GH", - ["c.ngle.s_3"] = "46000039VGH", - ["c.seq.s_2"] = "4600003aGH", - ["c.seq.s_3"] = "4600003aVGH", - ["c.ngl.s_2"] = "4600003bGH", - ["c.ngl.s_3"] = "4600003bVGH", - ["c.lt.s_2"] = "4600003cGH", - ["c.lt.s_3"] = "4600003cVGH", - ["c.nge.s_2"] = "4600003dGH", - ["c.nge.s_3"] = "4600003dVGH", - ["c.le.s_2"] = "4600003eGH", - ["c.le.s_3"] = "4600003eVGH", - ["c.ngt.s_2"] = "4600003fGH", - ["c.ngt.s_3"] = "4600003fVGH", - - ["add.d_3"] = "46200000FGH", - ["sub.d_3"] = "46200001FGH", - ["mul.d_3"] = "46200002FGH", - ["div.d_3"] = "46200003FGH", - ["sqrt.d_2"] = "46200004FG", - ["abs.d_2"] = "46200005FG", - ["mov.d_2"] = "46200006FG", - ["neg.d_2"] = "46200007FG", - ["round.l.d_2"] = "46200008FG", - ["trunc.l.d_2"] = "46200009FG", - ["ceil.l.d_2"] = "4620000aFG", - ["floor.l.d_2"] = "4620000bFG", - ["round.w.d_2"] = "4620000cFG", - ["trunc.w.d_2"] = "4620000dFG", - ["ceil.w.d_2"] = "4620000eFG", - ["floor.w.d_2"] = "4620000fFG", - ["movf.d_2"] = "46200011FG", - ["movf.d_3"] = "46200011FGC", - ["movt.d_2"] = "46210011FG", - ["movt.d_3"] = "46210011FGC", - ["movz.d_3"] = "46200012FGT", - ["movn.d_3"] = "46200013FGT", - ["recip.d_2"] = "46200015FG", - ["rsqrt.d_2"] = "46200016FG", - ["cvt.s.d_2"] = "46200020FG", - ["cvt.w.d_2"] = "46200024FG", - ["cvt.l.d_2"] = "46200025FG", - ["c.f.d_2"] = "46200030GH", - ["c.f.d_3"] = "46200030VGH", - ["c.un.d_2"] = "46200031GH", - ["c.un.d_3"] = "46200031VGH", - ["c.eq.d_2"] = "46200032GH", - ["c.eq.d_3"] = "46200032VGH", - ["c.ueq.d_2"] = "46200033GH", - ["c.ueq.d_3"] = "46200033VGH", - ["c.olt.d_2"] = "46200034GH", - ["c.olt.d_3"] = "46200034VGH", - ["c.ult.d_2"] = "46200035GH", - ["c.ult.d_3"] = "46200035VGH", - ["c.ole.d_2"] = "46200036GH", - ["c.ole.d_3"] = "46200036VGH", - ["c.ule.d_2"] = "46200037GH", - ["c.ule.d_3"] = "46200037VGH", - ["c.sf.d_2"] = "46200038GH", - ["c.sf.d_3"] = "46200038VGH", - ["c.ngle.d_2"] = "46200039GH", - ["c.ngle.d_3"] = "46200039VGH", - ["c.seq.d_2"] = "4620003aGH", - ["c.seq.d_3"] = "4620003aVGH", - ["c.ngl.d_2"] = "4620003bGH", - ["c.ngl.d_3"] = "4620003bVGH", - ["c.lt.d_2"] = "4620003cGH", - ["c.lt.d_3"] = "4620003cVGH", - ["c.nge.d_2"] = "4620003dGH", - ["c.nge.d_3"] = "4620003dVGH", - ["c.le.d_2"] = "4620003eGH", - ["c.le.d_3"] = "4620003eVGH", - ["c.ngt.d_2"] = "4620003fGH", - ["c.ngt.d_3"] = "4620003fVGH", - - ["add.ps_3"] = "46c00000FGH", - ["sub.ps_3"] = "46c00001FGH", - ["mul.ps_3"] = "46c00002FGH", - ["abs.ps_2"] = "46c00005FG", - ["mov.ps_2"] = "46c00006FG", - ["neg.ps_2"] = "46c00007FG", - ["movf.ps_2"] = "46c00011FG", - ["movf.ps_3"] = "46c00011FGC", - ["movt.ps_2"] = "46c10011FG", - ["movt.ps_3"] = "46c10011FGC", - ["movz.ps_3"] = "46c00012FGT", - ["movn.ps_3"] = "46c00013FGT", - ["cvt.s.pu_2"] = "46c00020FG", - ["cvt.s.pl_2"] = "46c00028FG", - ["pll.ps_3"] = "46c0002cFGH", - ["plu.ps_3"] = "46c0002dFGH", - ["pul.ps_3"] = "46c0002eFGH", - ["puu.ps_3"] = "46c0002fFGH", - ["c.f.ps_2"] = "46c00030GH", - ["c.f.ps_3"] = "46c00030VGH", - ["c.un.ps_2"] = "46c00031GH", - ["c.un.ps_3"] = "46c00031VGH", - ["c.eq.ps_2"] = "46c00032GH", - ["c.eq.ps_3"] = "46c00032VGH", - ["c.ueq.ps_2"] = "46c00033GH", - ["c.ueq.ps_3"] = "46c00033VGH", - ["c.olt.ps_2"] = "46c00034GH", - ["c.olt.ps_3"] = "46c00034VGH", - ["c.ult.ps_2"] = "46c00035GH", - ["c.ult.ps_3"] = "46c00035VGH", - ["c.ole.ps_2"] = "46c00036GH", - ["c.ole.ps_3"] = "46c00036VGH", - ["c.ule.ps_2"] = "46c00037GH", - ["c.ule.ps_3"] = "46c00037VGH", - ["c.sf.ps_2"] = "46c00038GH", - ["c.sf.ps_3"] = "46c00038VGH", - ["c.ngle.ps_2"] = "46c00039GH", - ["c.ngle.ps_3"] = "46c00039VGH", - ["c.seq.ps_2"] = "46c0003aGH", - ["c.seq.ps_3"] = "46c0003aVGH", - ["c.ngl.ps_2"] = "46c0003bGH", - ["c.ngl.ps_3"] = "46c0003bVGH", - ["c.lt.ps_2"] = "46c0003cGH", - ["c.lt.ps_3"] = "46c0003cVGH", - ["c.nge.ps_2"] = "46c0003dGH", - ["c.nge.ps_3"] = "46c0003dVGH", - ["c.le.ps_2"] = "46c0003eGH", - ["c.le.ps_3"] = "46c0003eVGH", - ["c.ngt.ps_2"] = "46c0003fGH", - ["c.ngt.ps_3"] = "46c0003fVGH", - - ["cvt.s.w_2"] = "46800020FG", - ["cvt.d.w_2"] = "46800021FG", - - ["cvt.s.l_2"] = "46a00020FG", - ["cvt.d.l_2"] = "46a00021FG", - - -- Opcode COP1X. - lwxc1_2 = "4c000000FX", - ldxc1_2 = "4c000001FX", - luxc1_2 = "4c000005FX", - swxc1_2 = "4c000008FX", - sdxc1_2 = "4c000009FX", - suxc1_2 = "4c00000dFX", - prefx_2 = "4c00000fMX", - ["alnv.ps_4"] = "4c00001eFGHS", - ["madd.s_4"] = "4c000020FRGH", - ["madd.d_4"] = "4c000021FRGH", - ["madd.ps_4"] = "4c000026FRGH", - ["msub.s_4"] = "4c000028FRGH", - ["msub.d_4"] = "4c000029FRGH", - ["msub.ps_4"] = "4c00002eFRGH", - ["nmadd.s_4"] = "4c000030FRGH", - ["nmadd.d_4"] = "4c000031FRGH", - ["nmadd.ps_4"] = "4c000036FRGH", - ["nmsub.s_4"] = "4c000038FRGH", - ["nmsub.d_4"] = "4c000039FRGH", - ["nmsub.ps_4"] = "4c00003eFRGH", -} - ------------------------------------------------------------------------------- - -local function parse_gpr(expr) - local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$") - local tp = map_type[tname or expr] - if tp then - local reg = ovreg or tp.reg - if not reg then - werror("type `"..(tname or expr).."' needs a register override") - end - expr = reg - end - local r = match(expr, "^r([1-3]?[0-9])$") - if r then - r = tonumber(r) - if r <= 31 then return r, tp end - end - werror("bad register name `"..expr.."'") -end - -local function parse_fpr(expr) - local r = match(expr, "^f([1-3]?[0-9])$") - if r then - r = tonumber(r) - if r <= 31 then return r end - end - werror("bad register name `"..expr.."'") -end - -local function parse_imm(imm, bits, shift, scale, signed) - local n = tonumber(imm) - if n then - local m = sar(n, scale) - if shl(m, scale) == n then - if signed then - local s = sar(m, bits-1) - if s == 0 then return shl(m, shift) - elseif s == -1 then return shl(m + shl(1, bits), shift) end - else - if sar(m, bits) == 0 then return shl(m, shift) end - end - end - werror("out of range immediate `"..imm.."'") - elseif match(imm, "^[rf]([1-3]?[0-9])$") or - match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then - werror("expected immediate operand, got register") - else - waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm) - return 0 - end -end - -local function parse_disp(disp) - local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") - if imm then - local r = shl(parse_gpr(reg), 21) - local extname = match(imm, "^extern%s+(%S+)$") - if extname then - waction("REL_EXT", map_extern[extname], nil, 1) - return r - else - return r + parse_imm(imm, 16, 0, 0, true) - end - end - local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") - if reg and tailr ~= "" then - local r, tp = parse_gpr(reg) - if tp then - waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) - return shl(r, 21) - end - end - werror("bad displacement `"..disp.."'") -end - -local function parse_index(idx) - local rt, rs = match(idx, "^(.*)%(([%w_:]+)%)$") - if rt then - rt = parse_gpr(rt) - rs = parse_gpr(rs) - return shl(rt, 16) + shl(rs, 21) - end - werror("bad index `"..idx.."'") -end - -local function parse_label(label, def) - local prefix = sub(label, 1, 2) - -- =>label (pc label reference) - if prefix == "=>" then - return "PC", 0, sub(label, 3) - end - -- ->name (global label reference) - if prefix == "->" then - return "LG", map_global[sub(label, 3)] - end - if def then - -- [1-9] (local label definition) - if match(label, "^[1-9]$") then - return "LG", 10+tonumber(label) - end - else - -- [<>][1-9] (local label reference) - local dir, lnum = match(label, "^([<>])([1-9])$") - if dir then -- Fwd: 1-9, Bkwd: 11-19. - return "LG", lnum + (dir == ">" and 0 or 10) - end - -- extern label (extern label reference) - local extname = match(label, "^extern%s+(%S+)$") - if extname then - return "EXT", map_extern[extname] - end - end - werror("bad label `"..label.."'") -end - ------------------------------------------------------------------------------- - --- Handle opcodes defined with template strings. -map_op[".template__"] = function(params, template, nparams) - if not params then return sub(template, 9) end - local op = tonumber(sub(template, 1, 8), 16) - local n = 1 - - -- Limit number of section buffer positions used by a single dasm_put(). - -- A single opcode needs a maximum of 2 positions (ins/ext). - if secpos+2 > maxsecpos then wflush() end - local pos = wpos() - - -- Process each character. - for p in gmatch(sub(template, 9), ".") do - if p == "D" then - op = op + shl(parse_gpr(params[n]), 11); n = n + 1 - elseif p == "T" then - op = op + shl(parse_gpr(params[n]), 16); n = n + 1 - elseif p == "S" then - op = op + shl(parse_gpr(params[n]), 21); n = n + 1 - elseif p == "F" then - op = op + shl(parse_fpr(params[n]), 6); n = n + 1 - elseif p == "G" then - op = op + shl(parse_fpr(params[n]), 11); n = n + 1 - elseif p == "H" then - op = op + shl(parse_fpr(params[n]), 16); n = n + 1 - elseif p == "R" then - op = op + shl(parse_fpr(params[n]), 21); n = n + 1 - elseif p == "I" then - op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1 - elseif p == "U" then - op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1 - elseif p == "O" then - op = op + parse_disp(params[n]); n = n + 1 - elseif p == "X" then - op = op + parse_index(params[n]); n = n + 1 - elseif p == "B" or p == "J" then - local mode, n, s = parse_label(params[n], false) - if p == "B" then n = n + 2048 end - waction("REL_"..mode, n, s, 1) - n = n + 1 - elseif p == "A" then - op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1 - elseif p == "M" then - op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1 - elseif p == "N" then - op = op + parse_imm(params[n], 5, 16, 0, false); n = n + 1 - elseif p == "C" then - op = op + parse_imm(params[n], 3, 18, 0, false); n = n + 1 - elseif p == "V" then - op = op + parse_imm(params[n], 3, 8, 0, false); n = n + 1 - elseif p == "W" then - op = op + parse_imm(params[n], 3, 0, 0, false); n = n + 1 - elseif p == "Y" then - op = op + parse_imm(params[n], 20, 6, 0, false); n = n + 1 - elseif p == "Z" then - op = op + parse_imm(params[n], 10, 6, 0, false); n = n + 1 - elseif p == "=" then - op = op + shl(band(op, 0xf800), 5) -- Copy D to T for clz, clo. - else - assert(false) - end - end - wputpos(pos, op) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode to mark the position where the action list is to be emitted. -map_op[".actionlist_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeactions(out, name) end) -end - --- Pseudo-opcode to mark the position where the global enum is to be emitted. -map_op[".globals_1"] = function(params) - if not params then return "prefix" end - local prefix = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobals(out, prefix) end) -end - --- Pseudo-opcode to mark the position where the global names are to be emitted. -map_op[".globalnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobalnames(out, name) end) -end - --- Pseudo-opcode to mark the position where the extern names are to be emitted. -map_op[".externnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeexternnames(out, name) end) -end - ------------------------------------------------------------------------------- - --- Label pseudo-opcode (converted from trailing colon form). -map_op[".label_1"] = function(params) - if not params then return "[1-9] | ->global | =>pcexpr" end - if secpos+1 > maxsecpos then wflush() end - local mode, n, s = parse_label(params[1], true) - if mode == "EXT" then werror("bad label definition") end - waction("LABEL_"..mode, n, s, 1) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcodes for data storage. -map_op[".long_*"] = function(params) - if not params then return "imm..." end - for _,p in ipairs(params) do - local n = tonumber(p) - if not n then werror("bad immediate `"..p.."'") end - if n < 0 then n = n + 2^32 end - wputw(n) - if secpos+2 > maxsecpos then wflush() end - end -end - --- Alignment pseudo-opcode. -map_op[".align_1"] = function(params) - if not params then return "numpow2" end - if secpos+1 > maxsecpos then wflush() end - local align = tonumber(params[1]) - if align then - local x = align - -- Must be a power of 2 in the range (2 ... 256). - for i=1,8 do - x = x / 2 - if x == 1 then - waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. - return - end - end - end - werror("bad alignment") -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode for (primitive) type definitions (map to C types). -map_op[".type_3"] = function(params, nparams) - if not params then - return nparams == 2 and "name, ctype" or "name, ctype, reg" - end - local name, ctype, reg = params[1], params[2], params[3] - if not match(name, "^[%a_][%w_]*$") then - werror("bad type name `"..name.."'") - end - local tp = map_type[name] - if tp then - werror("duplicate type `"..name.."'") - end - -- Add #type to defines. A bit unclean to put it in map_archdef. - map_archdef["#"..name] = "sizeof("..ctype..")" - -- Add new type and emit shortcut define. - local num = ctypenum + 1 - map_type[name] = { - ctype = ctype, - ctypefmt = format("Dt%X(%%s)", num), - reg = reg, - } - wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) - ctypenum = num -end -map_op[".type_2"] = map_op[".type_3"] - --- Dump type definitions. -local function dumptypes(out, lvl) - local t = {} - for name in pairs(map_type) do t[#t+1] = name end - sort(t) - out:write("Type definitions:\n") - for _,name in ipairs(t) do - local tp = map_type[name] - local reg = tp.reg or "" - out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Set the current section. -function _M.section(num) - waction("SECTION", num) - wflush(true) -- SECTION is a terminal action. -end - ------------------------------------------------------------------------------- - --- Dump architecture description. -function _M.dumparch(out) - out:write(format("DynASM %s version %s, released %s\n\n", - _info.arch, _info.version, _info.release)) - dumpactions(out) -end - --- Dump all user defined elements. -function _M.dumpdef(out, lvl) - dumptypes(out, lvl) - dumpglobals(out, lvl) - dumpexterns(out, lvl) -end - ------------------------------------------------------------------------------- - --- Pass callbacks from/to the DynASM core. -function _M.passcb(wl, we, wf, ww) - wline, werror, wfatal, wwarn = wl, we, wf, ww - return wflush -end - --- Setup the arch-specific module. -function _M.setup(arch, opt) - g_arch, g_opt = arch, opt -end - --- Merge the core maps and the arch-specific maps. -function _M.mergemaps(map_coreop, map_def) - setmetatable(map_op, { __index = map_coreop }) - setmetatable(map_def, { __index = map_archdef }) - return map_op, map_def -end - -return _M - ------------------------------------------------------------------------------- - diff --git a/core/src/luajit/dynasm/dasm_ppc.h b/core/src/luajit/dynasm/dasm_ppc.h deleted file mode 100644 index 7df493654..000000000 --- a/core/src/luajit/dynasm/dasm_ppc.h +++ /dev/null @@ -1,412 +0,0 @@ -/* -** DynASM PPC encoding engine. -** Copyright (C) 2005-2015 Mike Pall. All rights reserved. -** Released under the MIT license. See dynasm.lua for full copyright notice. -*/ - -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> - -#define DASM_ARCH "ppc" - -#ifndef DASM_EXTERN -#define DASM_EXTERN(a,b,c,d) 0 -#endif - -/* Action definitions. */ -enum { - DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT, - /* The following actions need a buffer position. */ - DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, - /* The following actions also have an argument. */ - DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, - DASM__MAX -}; - -/* Maximum number of section buffer positions for a single dasm_put() call. */ -#define DASM_MAXSECPOS 25 - -/* DynASM encoder status codes. Action list offset or number are or'ed in. */ -#define DASM_S_OK 0x00000000 -#define DASM_S_NOMEM 0x01000000 -#define DASM_S_PHASE 0x02000000 -#define DASM_S_MATCH_SEC 0x03000000 -#define DASM_S_RANGE_I 0x11000000 -#define DASM_S_RANGE_SEC 0x12000000 -#define DASM_S_RANGE_LG 0x13000000 -#define DASM_S_RANGE_PC 0x14000000 -#define DASM_S_RANGE_REL 0x15000000 -#define DASM_S_UNDEF_LG 0x21000000 -#define DASM_S_UNDEF_PC 0x22000000 - -/* Macros to convert positions (8 bit section + 24 bit index). */ -#define DASM_POS2IDX(pos) ((pos)&0x00ffffff) -#define DASM_POS2BIAS(pos) ((pos)&0xff000000) -#define DASM_SEC2POS(sec) ((sec)<<24) -#define DASM_POS2SEC(pos) ((pos)>>24) -#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) - -/* Action list type. */ -typedef const unsigned int *dasm_ActList; - -/* Per-section structure. */ -typedef struct dasm_Section { - int *rbuf; /* Biased buffer pointer (negative section bias). */ - int *buf; /* True buffer pointer. */ - size_t bsize; /* Buffer size in bytes. */ - int pos; /* Biased buffer position. */ - int epos; /* End of biased buffer position - max single put. */ - int ofs; /* Byte offset into section. */ -} dasm_Section; - -/* Core structure holding the DynASM encoding state. */ -struct dasm_State { - size_t psize; /* Allocated size of this structure. */ - dasm_ActList actionlist; /* Current actionlist pointer. */ - int *lglabels; /* Local/global chain/pos ptrs. */ - size_t lgsize; - int *pclabels; /* PC label chains/pos ptrs. */ - size_t pcsize; - void **globals; /* Array of globals (bias -10). */ - dasm_Section *section; /* Pointer to active section. */ - size_t codesize; /* Total size of all code sections. */ - int maxsection; /* 0 <= sectionidx < maxsection. */ - int status; /* Status code. */ - dasm_Section sections[1]; /* All sections. Alloc-extended. */ -}; - -/* The size of the core structure depends on the max. number of sections. */ -#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) - - -/* Initialize DynASM state. */ -void dasm_init(Dst_DECL, int maxsection) -{ - dasm_State *D; - size_t psz = 0; - int i; - Dst_REF = NULL; - DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); - D = Dst_REF; - D->psize = psz; - D->lglabels = NULL; - D->lgsize = 0; - D->pclabels = NULL; - D->pcsize = 0; - D->globals = NULL; - D->maxsection = maxsection; - for (i = 0; i < maxsection; i++) { - D->sections[i].buf = NULL; /* Need this for pass3. */ - D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); - D->sections[i].bsize = 0; - D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ - } -} - -/* Free DynASM state. */ -void dasm_free(Dst_DECL) -{ - dasm_State *D = Dst_REF; - int i; - for (i = 0; i < D->maxsection; i++) - if (D->sections[i].buf) - DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); - if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); - if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); - DASM_M_FREE(Dst, D, D->psize); -} - -/* Setup global label array. Must be called before dasm_setup(). */ -void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) -{ - dasm_State *D = Dst_REF; - D->globals = gl - 10; /* Negative bias to compensate for locals. */ - DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); -} - -/* Grow PC label array. Can be called after dasm_setup(), too. */ -void dasm_growpc(Dst_DECL, unsigned int maxpc) -{ - dasm_State *D = Dst_REF; - size_t osz = D->pcsize; - DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); - memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); -} - -/* Setup encoder. */ -void dasm_setup(Dst_DECL, const void *actionlist) -{ - dasm_State *D = Dst_REF; - int i; - D->actionlist = (dasm_ActList)actionlist; - D->status = DASM_S_OK; - D->section = &D->sections[0]; - memset((void *)D->lglabels, 0, D->lgsize); - if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); - for (i = 0; i < D->maxsection; i++) { - D->sections[i].pos = DASM_SEC2POS(i); - D->sections[i].ofs = 0; - } -} - - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) { \ - D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0) -#define CKPL(kind, st) \ - do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ - D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0) -#else -#define CK(x, st) ((void)0) -#define CKPL(kind, st) ((void)0) -#endif - -/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ -void dasm_put(Dst_DECL, int start, ...) -{ - va_list ap; - dasm_State *D = Dst_REF; - dasm_ActList p = D->actionlist + start; - dasm_Section *sec = D->section; - int pos = sec->pos, ofs = sec->ofs; - int *b; - - if (pos >= sec->epos) { - DASM_M_GROW(Dst, int, sec->buf, sec->bsize, - sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); - sec->rbuf = sec->buf - DASM_POS2BIAS(pos); - sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); - } - - b = sec->rbuf; - b[pos++] = start; - - va_start(ap, start); - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - if (action >= DASM__MAX) { - ofs += 4; - } else { - int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0; - switch (action) { - case DASM_STOP: goto stop; - case DASM_SECTION: - n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); - D->section = &D->sections[n]; goto stop; - case DASM_ESC: p++; ofs += 4; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; - case DASM_REL_LG: - n = (ins & 2047) - 10; pl = D->lglabels + n; - /* Bkwd rel or global. */ - if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; } - pl += 10; n = *pl; - if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ - goto linkrel; - case DASM_REL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putrel: - n = *pl; - if (n < 0) { /* Label exists. Get label pos and store it. */ - b[pos] = -n; - } else { - linkrel: - b[pos] = n; /* Else link to rel chain, anchored at label. */ - *pl = pos; - } - pos++; - break; - case DASM_LABEL_LG: - pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; - case DASM_LABEL_PC: - pl = D->pclabels + n; CKPL(pc, PC); - putlabel: - n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; - } - *pl = -pos; /* Label exists now. */ - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_IMM: -#ifdef DASM_CHECKS - CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I); -#endif - n >>= ((ins>>10)&31); -#ifdef DASM_CHECKS - if (ins & 0x8000) - CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I); - else - CK((n>>((ins>>5)&31)) == 0, RANGE_I); -#endif - b[pos++] = n; - break; - } - } - } -stop: - va_end(ap); - sec->pos = pos; - sec->ofs = ofs; -} -#undef CK - -/* Pass 2: Link sections, shrink aligns, fix label offsets. */ -int dasm_link(Dst_DECL, size_t *szp) -{ - dasm_State *D = Dst_REF; - int secnum; - int ofs = 0; - -#ifdef DASM_CHECKS - *szp = 0; - if (D->status != DASM_S_OK) return D->status; - { - int pc; - for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) - if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; - } -#endif - - { /* Handle globals not defined in this translation unit. */ - int idx; - for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { - int n = D->lglabels[idx]; - /* Undefined label: Collapse rel chain and replace with marker (< 0). */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } - } - } - - /* Combine all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->rbuf; - int pos = DASM_SEC2POS(secnum); - int lastpos = sec->pos; - - while (pos != lastpos) { - dasm_ActList p = D->actionlist + b[pos++]; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: p++; break; - case DASM_REL_EXT: break; - case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); break; - case DASM_REL_LG: case DASM_REL_PC: pos++; break; - case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; - case DASM_IMM: pos++; break; - } - } - stop: (void)0; - } - ofs += sec->ofs; /* Next section starts right after current section. */ - } - - D->codesize = ofs; /* Total size of all code sections */ - *szp = ofs; - return DASM_S_OK; -} - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0) -#else -#define CK(x, st) ((void)0) -#endif - -/* Pass 3: Encode sections. */ -int dasm_encode(Dst_DECL, void *buffer) -{ - dasm_State *D = Dst_REF; - char *base = (char *)buffer; - unsigned int *cp = (unsigned int *)buffer; - int secnum; - - /* Encode all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->buf; - int *endb = sec->rbuf + sec->pos; - - while (b != endb) { - dasm_ActList p = D->actionlist + *b++; - while (1) { - unsigned int ins = *p++; - unsigned int action = (ins >> 16); - int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0; - switch (action) { - case DASM_STOP: case DASM_SECTION: goto stop; - case DASM_ESC: *cp++ = *p++; break; - case DASM_REL_EXT: - n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins & 2047), 1) - 4; - goto patchrel; - case DASM_ALIGN: - ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; - break; - case DASM_REL_LG: - CK(n >= 0, UNDEF_LG); - case DASM_REL_PC: - CK(n >= 0, UNDEF_PC); - n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base); - patchrel: - CK((n & 3) == 0 && - (((n+4) + ((ins & 2048) ? 0x00008000 : 0x02000000)) >> - ((ins & 2048) ? 16 : 26)) == 0, RANGE_REL); - cp[-1] |= ((n+4) & ((ins & 2048) ? 0x0000fffc: 0x03fffffc)); - break; - case DASM_LABEL_LG: - ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); - break; - case DASM_LABEL_PC: break; - case DASM_IMM: - cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31); - break; - default: *cp++ = ins; break; - } - } - stop: (void)0; - } - } - - if (base + D->codesize != (char *)cp) /* Check for phase errors. */ - return DASM_S_PHASE; - return DASM_S_OK; -} -#undef CK - -/* Get PC label offset. */ -int dasm_getpclabel(Dst_DECL, unsigned int pc) -{ - dasm_State *D = Dst_REF; - if (pc*sizeof(int) < D->pcsize) { - int pos = D->pclabels[pc]; - if (pos < 0) return *DASM_POS2PTR(D, -pos); - if (pos > 0) return -1; /* Undefined. */ - } - return -2; /* Unused or out of range. */ -} - -#ifdef DASM_CHECKS -/* Optional sanity checker to call between isolated encoding steps. */ -int dasm_checkstep(Dst_DECL, int secmatch) -{ - dasm_State *D = Dst_REF; - if (D->status == DASM_S_OK) { - int i; - for (i = 1; i <= 9; i++) { - if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; } - D->lglabels[i] = 0; - } - } - if (D->status == DASM_S_OK && secmatch >= 0 && - D->section != &D->sections[secmatch]) - D->status = DASM_S_MATCH_SEC|(D->section-D->sections); - return D->status; -} -#endif - diff --git a/core/src/luajit/dynasm/dasm_ppc.lua b/core/src/luajit/dynasm/dasm_ppc.lua deleted file mode 100644 index 91f4ff9a4..000000000 --- a/core/src/luajit/dynasm/dasm_ppc.lua +++ /dev/null @@ -1,1249 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM PPC module. --- --- Copyright (C) 2005-2015 Mike Pall. All rights reserved. --- See dynasm.lua for full copyright notice. ------------------------------------------------------------------------------- - --- Module information: -local _info = { - arch = "ppc", - description = "DynASM PPC module", - version = "1.3.0", - vernum = 10300, - release = "2011-05-05", - author = "Mike Pall", - license = "MIT", -} - --- Exported glue functions for the arch-specific module. -local _M = { _info = _info } - --- Cache library functions. -local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs -local assert, setmetatable = assert, setmetatable -local _s = string -local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char -local match, gmatch = _s.match, _s.gmatch -local concat, sort = table.concat, table.sort -local bit = bit or require("bit") -local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift -local tohex = bit.tohex - --- Inherited tables and callbacks. -local g_opt, g_arch -local wline, werror, wfatal, wwarn - --- Action name list. --- CHECK: Keep this in sync with the C code! -local action_names = { - "STOP", "SECTION", "ESC", "REL_EXT", - "ALIGN", "REL_LG", "LABEL_LG", - "REL_PC", "LABEL_PC", "IMM", -} - --- Maximum number of section buffer positions for dasm_put(). --- CHECK: Keep this in sync with the C code! -local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. - --- Action name -> action number. -local map_action = {} -for n,name in ipairs(action_names) do - map_action[name] = n-1 -end - --- Action list buffer. -local actlist = {} - --- Argument list for next dasm_put(). Start with offset 0 into action list. -local actargs = { 0 } - --- Current number of section buffer positions for dasm_put(). -local secpos = 1 - ------------------------------------------------------------------------------- - --- Dump action names and numbers. -local function dumpactions(out) - out:write("DynASM encoding engine action codes:\n") - for n,name in ipairs(action_names) do - local num = map_action[name] - out:write(format(" %-10s %02X %d\n", name, num, num)) - end - out:write("\n") -end - --- Write action list buffer as a huge static C array. -local function writeactions(out, name) - local nn = #actlist - if nn == 0 then nn = 1; actlist[0] = map_action.STOP end - out:write("static const unsigned int ", name, "[", nn, "] = {\n") - for i = 1,nn-1 do - assert(out:write("0x", tohex(actlist[i]), ",\n")) - end - assert(out:write("0x", tohex(actlist[nn]), "\n};\n\n")) -end - ------------------------------------------------------------------------------- - --- Add word to action list. -local function wputxw(n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - actlist[#actlist+1] = n -end - --- Add action to list with optional arg. Advance buffer pos, too. -local function waction(action, val, a, num) - local w = assert(map_action[action], "bad action name `"..action.."'") - wputxw(w * 0x10000 + (val or 0)) - if a then actargs[#actargs+1] = a end - if a or num then secpos = secpos + (num or 1) end -end - --- Flush action list (intervening C code or buffer pos overflow). -local function wflush(term) - if #actlist == actargs[1] then return end -- Nothing to flush. - if not term then waction("STOP") end -- Terminate action list. - wline(format("dasm_put(Dst, %s);", concat(actargs, ", ")), true) - actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). - secpos = 1 -- The actionlist offset occupies a buffer position, too. -end - --- Put escaped word. -local function wputw(n) - if n <= 0xffffff then waction("ESC") end - wputxw(n) -end - --- Reserve position for word. -local function wpos() - local pos = #actlist+1 - actlist[pos] = "" - return pos -end - --- Store word to reserved position. -local function wputpos(pos, n) - assert(n >= 0 and n <= 0xffffffff and n % 1 == 0, "word out of range") - actlist[pos] = n -end - ------------------------------------------------------------------------------- - --- Global label name -> global label number. With auto assignment on 1st use. -local next_global = 20 -local map_global = setmetatable({}, { __index = function(t, name) - if not match(name, "^[%a_][%w_]*$") then werror("bad global label") end - local n = next_global - if n > 2047 then werror("too many global labels") end - next_global = n + 1 - t[name] = n - return n -end}) - --- Dump global labels. -local function dumpglobals(out, lvl) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("Global labels:\n") - for i=20,next_global-1 do - out:write(format(" %s\n", t[i])) - end - out:write("\n") -end - --- Write global label enum. -local function writeglobals(out, prefix) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("enum {\n") - for i=20,next_global-1 do - out:write(" ", prefix, t[i], ",\n") - end - out:write(" ", prefix, "_MAX\n};\n") -end - --- Write global label names. -local function writeglobalnames(out, name) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("static const char *const ", name, "[] = {\n") - for i=20,next_global-1 do - out:write(" \"", t[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Extern label name -> extern label number. With auto assignment on 1st use. -local next_extern = 0 -local map_extern_ = {} -local map_extern = setmetatable({}, { __index = function(t, name) - -- No restrictions on the name for now. - local n = next_extern - if n > 2047 then werror("too many extern labels") end - next_extern = n + 1 - t[name] = n - map_extern_[n] = name - return n -end}) - --- Dump extern labels. -local function dumpexterns(out, lvl) - out:write("Extern labels:\n") - for i=0,next_extern-1 do - out:write(format(" %s\n", map_extern_[i])) - end - out:write("\n") -end - --- Write extern label names. -local function writeexternnames(out, name) - out:write("static const char *const ", name, "[] = {\n") - for i=0,next_extern-1 do - out:write(" \"", map_extern_[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Arch-specific maps. -local map_archdef = { sp = "r1" } -- Ext. register name -> int. name. - -local map_type = {} -- Type name -> { ctype, reg } -local ctypenum = 0 -- Type number (for Dt... macros). - --- Reverse defines for registers. -function _M.revdef(s) - if s == "r1" then return "sp" end - return s -end - -local map_cond = { - lt = 0, gt = 1, eq = 2, so = 3, - ge = 4, le = 5, ne = 6, ns = 7, -} - ------------------------------------------------------------------------------- - --- Template strings for PPC instructions. -local map_op = { - tdi_3 = "08000000ARI", - twi_3 = "0c000000ARI", - mulli_3 = "1c000000RRI", - subfic_3 = "20000000RRI", - cmplwi_3 = "28000000XRU", - cmplwi_2 = "28000000-RU", - cmpldi_3 = "28200000XRU", - cmpldi_2 = "28200000-RU", - cmpwi_3 = "2c000000XRI", - cmpwi_2 = "2c000000-RI", - cmpdi_3 = "2c200000XRI", - cmpdi_2 = "2c200000-RI", - addic_3 = "30000000RRI", - ["addic._3"] = "34000000RRI", - addi_3 = "38000000RR0I", - li_2 = "38000000RI", - la_2 = "38000000RD", - addis_3 = "3c000000RR0I", - lis_2 = "3c000000RI", - lus_2 = "3c000000RU", - bc_3 = "40000000AAK", - bcl_3 = "40000001AAK", - bdnz_1 = "42000000K", - bdz_1 = "42400000K", - sc_0 = "44000000", - b_1 = "48000000J", - bl_1 = "48000001J", - rlwimi_5 = "50000000RR~AAA.", - rlwinm_5 = "54000000RR~AAA.", - rlwnm_5 = "5c000000RR~RAA.", - ori_3 = "60000000RR~U", - nop_0 = "60000000", - oris_3 = "64000000RR~U", - xori_3 = "68000000RR~U", - xoris_3 = "6c000000RR~U", - ["andi._3"] = "70000000RR~U", - ["andis._3"] = "74000000RR~U", - lwz_2 = "80000000RD", - lwzu_2 = "84000000RD", - lbz_2 = "88000000RD", - lbzu_2 = "8c000000RD", - stw_2 = "90000000RD", - stwu_2 = "94000000RD", - stb_2 = "98000000RD", - stbu_2 = "9c000000RD", - lhz_2 = "a0000000RD", - lhzu_2 = "a4000000RD", - lha_2 = "a8000000RD", - lhau_2 = "ac000000RD", - sth_2 = "b0000000RD", - sthu_2 = "b4000000RD", - lmw_2 = "b8000000RD", - stmw_2 = "bc000000RD", - lfs_2 = "c0000000FD", - lfsu_2 = "c4000000FD", - lfd_2 = "c8000000FD", - lfdu_2 = "cc000000FD", - stfs_2 = "d0000000FD", - stfsu_2 = "d4000000FD", - stfd_2 = "d8000000FD", - stfdu_2 = "dc000000FD", - ld_2 = "e8000000RD", -- NYI: displacement must be divisible by 4. - ldu_2 = "e8000001RD", - lwa_2 = "e8000002RD", - std_2 = "f8000000RD", - stdu_2 = "f8000001RD", - - -- Primary opcode 19: - mcrf_2 = "4c000000XX", - isync_0 = "4c00012c", - crnor_3 = "4c000042CCC", - crnot_2 = "4c000042CC=", - crandc_3 = "4c000102CCC", - crxor_3 = "4c000182CCC", - crclr_1 = "4c000182C==", - crnand_3 = "4c0001c2CCC", - crand_3 = "4c000202CCC", - creqv_3 = "4c000242CCC", - crset_1 = "4c000242C==", - crorc_3 = "4c000342CCC", - cror_3 = "4c000382CCC", - crmove_2 = "4c000382CC=", - bclr_2 = "4c000020AA", - bclrl_2 = "4c000021AA", - bcctr_2 = "4c000420AA", - bcctrl_2 = "4c000421AA", - blr_0 = "4e800020", - blrl_0 = "4e800021", - bctr_0 = "4e800420", - bctrl_0 = "4e800421", - - -- Primary opcode 31: - cmpw_3 = "7c000000XRR", - cmpw_2 = "7c000000-RR", - cmpd_3 = "7c200000XRR", - cmpd_2 = "7c200000-RR", - tw_3 = "7c000008ARR", - subfc_3 = "7c000010RRR.", - subc_3 = "7c000010RRR~.", - mulhdu_3 = "7c000012RRR.", - addc_3 = "7c000014RRR.", - mulhwu_3 = "7c000016RRR.", - isel_4 = "7c00001eRRRC", - isellt_3 = "7c00001eRRR", - iselgt_3 = "7c00005eRRR", - iseleq_3 = "7c00009eRRR", - mfcr_1 = "7c000026R", - mfocrf_2 = "7c100026RG", - mtcrf_2 = "7c000120GR", - mtocrf_2 = "7c100120GR", - lwarx_3 = "7c000028RR0R", - ldx_3 = "7c00002aRR0R", - lwzx_3 = "7c00002eRR0R", - slw_3 = "7c000030RR~R.", - cntlzw_2 = "7c000034RR~", - sld_3 = "7c000036RR~R.", - and_3 = "7c000038RR~R.", - cmplw_3 = "7c000040XRR", - cmplw_2 = "7c000040-RR", - cmpld_3 = "7c200040XRR", - cmpld_2 = "7c200040-RR", - subf_3 = "7c000050RRR.", - sub_3 = "7c000050RRR~.", - ldux_3 = "7c00006aRR0R", - dcbst_2 = "7c00006c-RR", - lwzux_3 = "7c00006eRR0R", - cntlzd_2 = "7c000074RR~", - andc_3 = "7c000078RR~R.", - td_3 = "7c000088ARR", - mulhd_3 = "7c000092RRR.", - mulhw_3 = "7c000096RRR.", - ldarx_3 = "7c0000a8RR0R", - dcbf_2 = "7c0000ac-RR", - lbzx_3 = "7c0000aeRR0R", - neg_2 = "7c0000d0RR.", - lbzux_3 = "7c0000eeRR0R", - popcntb_2 = "7c0000f4RR~", - not_2 = "7c0000f8RR~%.", - nor_3 = "7c0000f8RR~R.", - subfe_3 = "7c000110RRR.", - sube_3 = "7c000110RRR~.", - adde_3 = "7c000114RRR.", - stdx_3 = "7c00012aRR0R", - stwcx_3 = "7c00012cRR0R.", - stwx_3 = "7c00012eRR0R", - prtyw_2 = "7c000134RR~", - stdux_3 = "7c00016aRR0R", - stwux_3 = "7c00016eRR0R", - prtyd_2 = "7c000174RR~", - subfze_2 = "7c000190RR.", - addze_2 = "7c000194RR.", - stdcx_3 = "7c0001acRR0R.", - stbx_3 = "7c0001aeRR0R", - subfme_2 = "7c0001d0RR.", - mulld_3 = "7c0001d2RRR.", - addme_2 = "7c0001d4RR.", - mullw_3 = "7c0001d6RRR.", - dcbtst_2 = "7c0001ec-RR", - stbux_3 = "7c0001eeRR0R", - add_3 = "7c000214RRR.", - dcbt_2 = "7c00022c-RR", - lhzx_3 = "7c00022eRR0R", - eqv_3 = "7c000238RR~R.", - eciwx_3 = "7c00026cRR0R", - lhzux_3 = "7c00026eRR0R", - xor_3 = "7c000278RR~R.", - mfspefscr_1 = "7c0082a6R", - mfxer_1 = "7c0102a6R", - mflr_1 = "7c0802a6R", - mfctr_1 = "7c0902a6R", - lwax_3 = "7c0002aaRR0R", - lhax_3 = "7c0002aeRR0R", - mftb_1 = "7c0c42e6R", - mftbu_1 = "7c0d42e6R", - lwaux_3 = "7c0002eaRR0R", - lhaux_3 = "7c0002eeRR0R", - sthx_3 = "7c00032eRR0R", - orc_3 = "7c000338RR~R.", - ecowx_3 = "7c00036cRR0R", - sthux_3 = "7c00036eRR0R", - or_3 = "7c000378RR~R.", - mr_2 = "7c000378RR~%.", - divdu_3 = "7c000392RRR.", - divwu_3 = "7c000396RRR.", - mtspefscr_1 = "7c0083a6R", - mtxer_1 = "7c0103a6R", - mtlr_1 = "7c0803a6R", - mtctr_1 = "7c0903a6R", - dcbi_2 = "7c0003ac-RR", - nand_3 = "7c0003b8RR~R.", - divd_3 = "7c0003d2RRR.", - divw_3 = "7c0003d6RRR.", - cmpb_3 = "7c0003f8RR~R.", - mcrxr_1 = "7c000400X", - subfco_3 = "7c000410RRR.", - subco_3 = "7c000410RRR~.", - addco_3 = "7c000414RRR.", - ldbrx_3 = "7c000428RR0R", - lswx_3 = "7c00042aRR0R", - lwbrx_3 = "7c00042cRR0R", - lfsx_3 = "7c00042eFR0R", - srw_3 = "7c000430RR~R.", - srd_3 = "7c000436RR~R.", - subfo_3 = "7c000450RRR.", - subo_3 = "7c000450RRR~.", - lfsux_3 = "7c00046eFR0R", - lswi_3 = "7c0004aaRR0A", - sync_0 = "7c0004ac", - lwsync_0 = "7c2004ac", - ptesync_0 = "7c4004ac", - lfdx_3 = "7c0004aeFR0R", - nego_2 = "7c0004d0RR.", - lfdux_3 = "7c0004eeFR0R", - subfeo_3 = "7c000510RRR.", - subeo_3 = "7c000510RRR~.", - addeo_3 = "7c000514RRR.", - stdbrx_3 = "7c000528RR0R", - stswx_3 = "7c00052aRR0R", - stwbrx_3 = "7c00052cRR0R", - stfsx_3 = "7c00052eFR0R", - stfsux_3 = "7c00056eFR0R", - subfzeo_2 = "7c000590RR.", - addzeo_2 = "7c000594RR.", - stswi_3 = "7c0005aaRR0A", - stfdx_3 = "7c0005aeFR0R", - subfmeo_2 = "7c0005d0RR.", - mulldo_3 = "7c0005d2RRR.", - addmeo_2 = "7c0005d4RR.", - mullwo_3 = "7c0005d6RRR.", - dcba_2 = "7c0005ec-RR", - stfdux_3 = "7c0005eeFR0R", - addo_3 = "7c000614RRR.", - lhbrx_3 = "7c00062cRR0R", - sraw_3 = "7c000630RR~R.", - srad_3 = "7c000634RR~R.", - srawi_3 = "7c000670RR~A.", - sradi_3 = "7c000674RR~H.", - eieio_0 = "7c0006ac", - lfiwax_3 = "7c0006aeFR0R", - sthbrx_3 = "7c00072cRR0R", - extsh_2 = "7c000734RR~.", - extsb_2 = "7c000774RR~.", - divduo_3 = "7c000792RRR.", - divwou_3 = "7c000796RRR.", - icbi_2 = "7c0007ac-RR", - stfiwx_3 = "7c0007aeFR0R", - extsw_2 = "7c0007b4RR~.", - divdo_3 = "7c0007d2RRR.", - divwo_3 = "7c0007d6RRR.", - dcbz_2 = "7c0007ec-RR", - - -- Primary opcode 30: - rldicl_4 = "78000000RR~HM.", - rldicr_4 = "78000004RR~HM.", - rldic_4 = "78000008RR~HM.", - rldimi_4 = "7800000cRR~HM.", - rldcl_4 = "78000010RR~RM.", - rldcr_4 = "78000012RR~RM.", - - -- Primary opcode 59: - fdivs_3 = "ec000024FFF.", - fsubs_3 = "ec000028FFF.", - fadds_3 = "ec00002aFFF.", - fsqrts_2 = "ec00002cF-F.", - fres_2 = "ec000030F-F.", - fmuls_3 = "ec000032FF-F.", - frsqrtes_2 = "ec000034F-F.", - fmsubs_4 = "ec000038FFFF~.", - fmadds_4 = "ec00003aFFFF~.", - fnmsubs_4 = "ec00003cFFFF~.", - fnmadds_4 = "ec00003eFFFF~.", - - -- Primary opcode 63: - fdiv_3 = "fc000024FFF.", - fsub_3 = "fc000028FFF.", - fadd_3 = "fc00002aFFF.", - fsqrt_2 = "fc00002cF-F.", - fsel_4 = "fc00002eFFFF~.", - fre_2 = "fc000030F-F.", - fmul_3 = "fc000032FF-F.", - frsqrte_2 = "fc000034F-F.", - fmsub_4 = "fc000038FFFF~.", - fmadd_4 = "fc00003aFFFF~.", - fnmsub_4 = "fc00003cFFFF~.", - fnmadd_4 = "fc00003eFFFF~.", - fcmpu_3 = "fc000000XFF", - fcpsgn_3 = "fc000010FFF.", - fcmpo_3 = "fc000040XFF", - mtfsb1_1 = "fc00004cA", - fneg_2 = "fc000050F-F.", - mcrfs_2 = "fc000080XX", - mtfsb0_1 = "fc00008cA", - fmr_2 = "fc000090F-F.", - frsp_2 = "fc000018F-F.", - fctiw_2 = "fc00001cF-F.", - fctiwz_2 = "fc00001eF-F.", - mtfsfi_2 = "fc00010cAA", -- NYI: upshift. - fnabs_2 = "fc000110F-F.", - fabs_2 = "fc000210F-F.", - frin_2 = "fc000310F-F.", - friz_2 = "fc000350F-F.", - frip_2 = "fc000390F-F.", - frim_2 = "fc0003d0F-F.", - mffs_1 = "fc00048eF.", - -- NYI: mtfsf, mtfsb0, mtfsb1. - fctid_2 = "fc00065cF-F.", - fctidz_2 = "fc00065eF-F.", - fcfid_2 = "fc00069cF-F.", - - -- Primary opcode 4, SPE APU extension: - evaddw_3 = "10000200RRR", - evaddiw_3 = "10000202RAR~", - evsubw_3 = "10000204RRR~", - evsubiw_3 = "10000206RAR~", - evabs_2 = "10000208RR", - evneg_2 = "10000209RR", - evextsb_2 = "1000020aRR", - evextsh_2 = "1000020bRR", - evrndw_2 = "1000020cRR", - evcntlzw_2 = "1000020dRR", - evcntlsw_2 = "1000020eRR", - brinc_3 = "1000020fRRR", - evand_3 = "10000211RRR", - evandc_3 = "10000212RRR", - evxor_3 = "10000216RRR", - evor_3 = "10000217RRR", - evmr_2 = "10000217RR=", - evnor_3 = "10000218RRR", - evnot_2 = "10000218RR=", - eveqv_3 = "10000219RRR", - evorc_3 = "1000021bRRR", - evnand_3 = "1000021eRRR", - evsrwu_3 = "10000220RRR", - evsrws_3 = "10000221RRR", - evsrwiu_3 = "10000222RRA", - evsrwis_3 = "10000223RRA", - evslw_3 = "10000224RRR", - evslwi_3 = "10000226RRA", - evrlw_3 = "10000228RRR", - evsplati_2 = "10000229RS", - evrlwi_3 = "1000022aRRA", - evsplatfi_2 = "1000022bRS", - evmergehi_3 = "1000022cRRR", - evmergelo_3 = "1000022dRRR", - evcmpgtu_3 = "10000230XRR", - evcmpgtu_2 = "10000230-RR", - evcmpgts_3 = "10000231XRR", - evcmpgts_2 = "10000231-RR", - evcmpltu_3 = "10000232XRR", - evcmpltu_2 = "10000232-RR", - evcmplts_3 = "10000233XRR", - evcmplts_2 = "10000233-RR", - evcmpeq_3 = "10000234XRR", - evcmpeq_2 = "10000234-RR", - evsel_4 = "10000278RRRW", - evsel_3 = "10000278RRR", - evfsadd_3 = "10000280RRR", - evfssub_3 = "10000281RRR", - evfsabs_2 = "10000284RR", - evfsnabs_2 = "10000285RR", - evfsneg_2 = "10000286RR", - evfsmul_3 = "10000288RRR", - evfsdiv_3 = "10000289RRR", - evfscmpgt_3 = "1000028cXRR", - evfscmpgt_2 = "1000028c-RR", - evfscmplt_3 = "1000028dXRR", - evfscmplt_2 = "1000028d-RR", - evfscmpeq_3 = "1000028eXRR", - evfscmpeq_2 = "1000028e-RR", - evfscfui_2 = "10000290R-R", - evfscfsi_2 = "10000291R-R", - evfscfuf_2 = "10000292R-R", - evfscfsf_2 = "10000293R-R", - evfsctui_2 = "10000294R-R", - evfsctsi_2 = "10000295R-R", - evfsctuf_2 = "10000296R-R", - evfsctsf_2 = "10000297R-R", - evfsctuiz_2 = "10000298R-R", - evfsctsiz_2 = "1000029aR-R", - evfststgt_3 = "1000029cXRR", - evfststgt_2 = "1000029c-RR", - evfststlt_3 = "1000029dXRR", - evfststlt_2 = "1000029d-RR", - evfststeq_3 = "1000029eXRR", - evfststeq_2 = "1000029e-RR", - efsadd_3 = "100002c0RRR", - efssub_3 = "100002c1RRR", - efsabs_2 = "100002c4RR", - efsnabs_2 = "100002c5RR", - efsneg_2 = "100002c6RR", - efsmul_3 = "100002c8RRR", - efsdiv_3 = "100002c9RRR", - efscmpgt_3 = "100002ccXRR", - efscmpgt_2 = "100002cc-RR", - efscmplt_3 = "100002cdXRR", - efscmplt_2 = "100002cd-RR", - efscmpeq_3 = "100002ceXRR", - efscmpeq_2 = "100002ce-RR", - efscfd_2 = "100002cfR-R", - efscfui_2 = "100002d0R-R", - efscfsi_2 = "100002d1R-R", - efscfuf_2 = "100002d2R-R", - efscfsf_2 = "100002d3R-R", - efsctui_2 = "100002d4R-R", - efsctsi_2 = "100002d5R-R", - efsctuf_2 = "100002d6R-R", - efsctsf_2 = "100002d7R-R", - efsctuiz_2 = "100002d8R-R", - efsctsiz_2 = "100002daR-R", - efststgt_3 = "100002dcXRR", - efststgt_2 = "100002dc-RR", - efststlt_3 = "100002ddXRR", - efststlt_2 = "100002dd-RR", - efststeq_3 = "100002deXRR", - efststeq_2 = "100002de-RR", - efdadd_3 = "100002e0RRR", - efdsub_3 = "100002e1RRR", - efdcfuid_2 = "100002e2R-R", - efdcfsid_2 = "100002e3R-R", - efdabs_2 = "100002e4RR", - efdnabs_2 = "100002e5RR", - efdneg_2 = "100002e6RR", - efdmul_3 = "100002e8RRR", - efddiv_3 = "100002e9RRR", - efdctuidz_2 = "100002eaR-R", - efdctsidz_2 = "100002ebR-R", - efdcmpgt_3 = "100002ecXRR", - efdcmpgt_2 = "100002ec-RR", - efdcmplt_3 = "100002edXRR", - efdcmplt_2 = "100002ed-RR", - efdcmpeq_3 = "100002eeXRR", - efdcmpeq_2 = "100002ee-RR", - efdcfs_2 = "100002efR-R", - efdcfui_2 = "100002f0R-R", - efdcfsi_2 = "100002f1R-R", - efdcfuf_2 = "100002f2R-R", - efdcfsf_2 = "100002f3R-R", - efdctui_2 = "100002f4R-R", - efdctsi_2 = "100002f5R-R", - efdctuf_2 = "100002f6R-R", - efdctsf_2 = "100002f7R-R", - efdctuiz_2 = "100002f8R-R", - efdctsiz_2 = "100002faR-R", - efdtstgt_3 = "100002fcXRR", - efdtstgt_2 = "100002fc-RR", - efdtstlt_3 = "100002fdXRR", - efdtstlt_2 = "100002fd-RR", - efdtsteq_3 = "100002feXRR", - efdtsteq_2 = "100002fe-RR", - evlddx_3 = "10000300RR0R", - evldd_2 = "10000301R8", - evldwx_3 = "10000302RR0R", - evldw_2 = "10000303R8", - evldhx_3 = "10000304RR0R", - evldh_2 = "10000305R8", - evlwhex_3 = "10000310RR0R", - evlwhe_2 = "10000311R4", - evlwhoux_3 = "10000314RR0R", - evlwhou_2 = "10000315R4", - evlwhosx_3 = "10000316RR0R", - evlwhos_2 = "10000317R4", - evstddx_3 = "10000320RR0R", - evstdd_2 = "10000321R8", - evstdwx_3 = "10000322RR0R", - evstdw_2 = "10000323R8", - evstdhx_3 = "10000324RR0R", - evstdh_2 = "10000325R8", - evstwhex_3 = "10000330RR0R", - evstwhe_2 = "10000331R4", - evstwhox_3 = "10000334RR0R", - evstwho_2 = "10000335R4", - evstwwex_3 = "10000338RR0R", - evstwwe_2 = "10000339R4", - evstwwox_3 = "1000033cRR0R", - evstwwo_2 = "1000033dR4", - evmhessf_3 = "10000403RRR", - evmhossf_3 = "10000407RRR", - evmheumi_3 = "10000408RRR", - evmhesmi_3 = "10000409RRR", - evmhesmf_3 = "1000040bRRR", - evmhoumi_3 = "1000040cRRR", - evmhosmi_3 = "1000040dRRR", - evmhosmf_3 = "1000040fRRR", - evmhessfa_3 = "10000423RRR", - evmhossfa_3 = "10000427RRR", - evmheumia_3 = "10000428RRR", - evmhesmia_3 = "10000429RRR", - evmhesmfa_3 = "1000042bRRR", - evmhoumia_3 = "1000042cRRR", - evmhosmia_3 = "1000042dRRR", - evmhosmfa_3 = "1000042fRRR", - evmwhssf_3 = "10000447RRR", - evmwlumi_3 = "10000448RRR", - evmwhumi_3 = "1000044cRRR", - evmwhsmi_3 = "1000044dRRR", - evmwhsmf_3 = "1000044fRRR", - evmwssf_3 = "10000453RRR", - evmwumi_3 = "10000458RRR", - evmwsmi_3 = "10000459RRR", - evmwsmf_3 = "1000045bRRR", - evmwhssfa_3 = "10000467RRR", - evmwlumia_3 = "10000468RRR", - evmwhumia_3 = "1000046cRRR", - evmwhsmia_3 = "1000046dRRR", - evmwhsmfa_3 = "1000046fRRR", - evmwssfa_3 = "10000473RRR", - evmwumia_3 = "10000478RRR", - evmwsmia_3 = "10000479RRR", - evmwsmfa_3 = "1000047bRRR", - evmra_2 = "100004c4RR", - evdivws_3 = "100004c6RRR", - evdivwu_3 = "100004c7RRR", - evmwssfaa_3 = "10000553RRR", - evmwumiaa_3 = "10000558RRR", - evmwsmiaa_3 = "10000559RRR", - evmwsmfaa_3 = "1000055bRRR", - evmwssfan_3 = "100005d3RRR", - evmwumian_3 = "100005d8RRR", - evmwsmian_3 = "100005d9RRR", - evmwsmfan_3 = "100005dbRRR", - evmergehilo_3 = "1000022eRRR", - evmergelohi_3 = "1000022fRRR", - evlhhesplatx_3 = "10000308RR0R", - evlhhesplat_2 = "10000309R2", - evlhhousplatx_3 = "1000030cRR0R", - evlhhousplat_2 = "1000030dR2", - evlhhossplatx_3 = "1000030eRR0R", - evlhhossplat_2 = "1000030fR2", - evlwwsplatx_3 = "10000318RR0R", - evlwwsplat_2 = "10000319R4", - evlwhsplatx_3 = "1000031cRR0R", - evlwhsplat_2 = "1000031dR4", - evaddusiaaw_2 = "100004c0RR", - evaddssiaaw_2 = "100004c1RR", - evsubfusiaaw_2 = "100004c2RR", - evsubfssiaaw_2 = "100004c3RR", - evaddumiaaw_2 = "100004c8RR", - evaddsmiaaw_2 = "100004c9RR", - evsubfumiaaw_2 = "100004caRR", - evsubfsmiaaw_2 = "100004cbRR", - evmheusiaaw_3 = "10000500RRR", - evmhessiaaw_3 = "10000501RRR", - evmhessfaaw_3 = "10000503RRR", - evmhousiaaw_3 = "10000504RRR", - evmhossiaaw_3 = "10000505RRR", - evmhossfaaw_3 = "10000507RRR", - evmheumiaaw_3 = "10000508RRR", - evmhesmiaaw_3 = "10000509RRR", - evmhesmfaaw_3 = "1000050bRRR", - evmhoumiaaw_3 = "1000050cRRR", - evmhosmiaaw_3 = "1000050dRRR", - evmhosmfaaw_3 = "1000050fRRR", - evmhegumiaa_3 = "10000528RRR", - evmhegsmiaa_3 = "10000529RRR", - evmhegsmfaa_3 = "1000052bRRR", - evmhogumiaa_3 = "1000052cRRR", - evmhogsmiaa_3 = "1000052dRRR", - evmhogsmfaa_3 = "1000052fRRR", - evmwlusiaaw_3 = "10000540RRR", - evmwlssiaaw_3 = "10000541RRR", - evmwlumiaaw_3 = "10000548RRR", - evmwlsmiaaw_3 = "10000549RRR", - evmheusianw_3 = "10000580RRR", - evmhessianw_3 = "10000581RRR", - evmhessfanw_3 = "10000583RRR", - evmhousianw_3 = "10000584RRR", - evmhossianw_3 = "10000585RRR", - evmhossfanw_3 = "10000587RRR", - evmheumianw_3 = "10000588RRR", - evmhesmianw_3 = "10000589RRR", - evmhesmfanw_3 = "1000058bRRR", - evmhoumianw_3 = "1000058cRRR", - evmhosmianw_3 = "1000058dRRR", - evmhosmfanw_3 = "1000058fRRR", - evmhegumian_3 = "100005a8RRR", - evmhegsmian_3 = "100005a9RRR", - evmhegsmfan_3 = "100005abRRR", - evmhogumian_3 = "100005acRRR", - evmhogsmian_3 = "100005adRRR", - evmhogsmfan_3 = "100005afRRR", - evmwlusianw_3 = "100005c0RRR", - evmwlssianw_3 = "100005c1RRR", - evmwlumianw_3 = "100005c8RRR", - evmwlsmianw_3 = "100005c9RRR", - - -- NYI: Book E instructions. -} - --- Add mnemonics for "." variants. -do - local t = {} - for k,v in pairs(map_op) do - if sub(v, -1) == "." then - local v2 = sub(v, 1, 7)..char(byte(v, 8)+1)..sub(v, 9, -2) - t[sub(k, 1, -3).."."..sub(k, -2)] = v2 - end - end - for k,v in pairs(t) do - map_op[k] = v - end -end - --- Add more branch mnemonics. -for cond,c in pairs(map_cond) do - local b1 = "b"..cond - local c1 = shl(band(c, 3), 16) + (c < 4 and 0x01000000 or 0) - -- bX[l] - map_op[b1.."_1"] = tohex(0x40800000 + c1).."K" - map_op[b1.."y_1"] = tohex(0x40a00000 + c1).."K" - map_op[b1.."l_1"] = tohex(0x40800001 + c1).."K" - map_op[b1.."_2"] = tohex(0x40800000 + c1).."-XK" - map_op[b1.."y_2"] = tohex(0x40a00000 + c1).."-XK" - map_op[b1.."l_2"] = tohex(0x40800001 + c1).."-XK" - -- bXlr[l] - map_op[b1.."lr_0"] = tohex(0x4c800020 + c1) - map_op[b1.."lrl_0"] = tohex(0x4c800021 + c1) - map_op[b1.."ctr_0"] = tohex(0x4c800420 + c1) - map_op[b1.."ctrl_0"] = tohex(0x4c800421 + c1) - -- bXctr[l] - map_op[b1.."lr_1"] = tohex(0x4c800020 + c1).."-X" - map_op[b1.."lrl_1"] = tohex(0x4c800021 + c1).."-X" - map_op[b1.."ctr_1"] = tohex(0x4c800420 + c1).."-X" - map_op[b1.."ctrl_1"] = tohex(0x4c800421 + c1).."-X" -end - ------------------------------------------------------------------------------- - -local function parse_gpr(expr) - local tname, ovreg = match(expr, "^([%w_]+):(r[1-3]?[0-9])$") - local tp = map_type[tname or expr] - if tp then - local reg = ovreg or tp.reg - if not reg then - werror("type `"..(tname or expr).."' needs a register override") - end - expr = reg - end - local r = match(expr, "^r([1-3]?[0-9])$") - if r then - r = tonumber(r) - if r <= 31 then return r, tp end - end - werror("bad register name `"..expr.."'") -end - -local function parse_fpr(expr) - local r = match(expr, "^f([1-3]?[0-9])$") - if r then - r = tonumber(r) - if r <= 31 then return r end - end - werror("bad register name `"..expr.."'") -end - -local function parse_cr(expr) - local r = match(expr, "^cr([0-7])$") - if r then return tonumber(r) end - werror("bad condition register name `"..expr.."'") -end - -local function parse_cond(expr) - local r, cond = match(expr, "^4%*cr([0-7])%+(%w%w)$") - if r then - r = tonumber(r) - local c = map_cond[cond] - if c and c < 4 then return r*4+c end - end - werror("bad condition bit name `"..expr.."'") -end - -local function parse_imm(imm, bits, shift, scale, signed) - local n = tonumber(imm) - if n then - local m = sar(n, scale) - if shl(m, scale) == n then - if signed then - local s = sar(m, bits-1) - if s == 0 then return shl(m, shift) - elseif s == -1 then return shl(m + shl(1, bits), shift) end - else - if sar(m, bits) == 0 then return shl(m, shift) end - end - end - werror("out of range immediate `"..imm.."'") - elseif match(imm, "^r([1-3]?[0-9])$") or - match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then - werror("expected immediate operand, got register") - else - waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm) - return 0 - end -end - -local function parse_shiftmask(imm, isshift) - local n = tonumber(imm) - if n then - if shr(n, 6) == 0 then - local lsb = band(imm, 31) - local msb = imm - lsb - return isshift and (shl(lsb, 11)+shr(msb, 4)) or (shl(lsb, 6)+msb) - end - werror("out of range immediate `"..imm.."'") - elseif match(imm, "^r([1-3]?[0-9])$") or - match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then - werror("expected immediate operand, got register") - else - werror("NYI: parameterized 64 bit shift/mask") - end -end - -local function parse_disp(disp) - local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") - if imm then - local r = parse_gpr(reg) - if r == 0 then werror("cannot use r0 in displacement") end - return shl(r, 16) + parse_imm(imm, 16, 0, 0, true) - end - local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") - if reg and tailr ~= "" then - local r, tp = parse_gpr(reg) - if r == 0 then werror("cannot use r0 in displacement") end - if tp then - waction("IMM", 32768+16*32, format(tp.ctypefmt, tailr)) - return shl(r, 16) - end - end - werror("bad displacement `"..disp.."'") -end - -local function parse_u5disp(disp, scale) - local imm, reg = match(disp, "^(.*)%(([%w_:]+)%)$") - if imm then - local r = parse_gpr(reg) - if r == 0 then werror("cannot use r0 in displacement") end - return shl(r, 16) + parse_imm(imm, 5, 11, scale, false) - end - local reg, tailr = match(disp, "^([%w_:]+)%s*(.*)$") - if reg and tailr ~= "" then - local r, tp = parse_gpr(reg) - if r == 0 then werror("cannot use r0 in displacement") end - if tp then - waction("IMM", scale*1024+5*32+11, format(tp.ctypefmt, tailr)) - return shl(r, 16) - end - end - werror("bad displacement `"..disp.."'") -end - -local function parse_label(label, def) - local prefix = sub(label, 1, 2) - -- =>label (pc label reference) - if prefix == "=>" then - return "PC", 0, sub(label, 3) - end - -- ->name (global label reference) - if prefix == "->" then - return "LG", map_global[sub(label, 3)] - end - if def then - -- [1-9] (local label definition) - if match(label, "^[1-9]$") then - return "LG", 10+tonumber(label) - end - else - -- [<>][1-9] (local label reference) - local dir, lnum = match(label, "^([<>])([1-9])$") - if dir then -- Fwd: 1-9, Bkwd: 11-19. - return "LG", lnum + (dir == ">" and 0 or 10) - end - -- extern label (extern label reference) - local extname = match(label, "^extern%s+(%S+)$") - if extname then - return "EXT", map_extern[extname] - end - end - werror("bad label `"..label.."'") -end - ------------------------------------------------------------------------------- - --- Handle opcodes defined with template strings. -map_op[".template__"] = function(params, template, nparams) - if not params then return sub(template, 9) end - local op = tonumber(sub(template, 1, 8), 16) - local n, rs = 1, 26 - - -- Limit number of section buffer positions used by a single dasm_put(). - -- A single opcode needs a maximum of 3 positions (rlwinm). - if secpos+3 > maxsecpos then wflush() end - local pos = wpos() - - -- Process each character. - for p in gmatch(sub(template, 9), ".") do - if p == "R" then - rs = rs - 5; op = op + shl(parse_gpr(params[n]), rs); n = n + 1 - elseif p == "F" then - rs = rs - 5; op = op + shl(parse_fpr(params[n]), rs); n = n + 1 - elseif p == "A" then - rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1 - elseif p == "S" then - rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, true); n = n + 1 - elseif p == "I" then - op = op + parse_imm(params[n], 16, 0, 0, true); n = n + 1 - elseif p == "U" then - op = op + parse_imm(params[n], 16, 0, 0, false); n = n + 1 - elseif p == "D" then - op = op + parse_disp(params[n]); n = n + 1 - elseif p == "2" then - op = op + parse_u5disp(params[n], 1); n = n + 1 - elseif p == "4" then - op = op + parse_u5disp(params[n], 2); n = n + 1 - elseif p == "8" then - op = op + parse_u5disp(params[n], 3); n = n + 1 - elseif p == "C" then - rs = rs - 5; op = op + shl(parse_cond(params[n]), rs); n = n + 1 - elseif p == "X" then - rs = rs - 5; op = op + shl(parse_cr(params[n]), rs+2); n = n + 1 - elseif p == "W" then - op = op + parse_cr(params[n]); n = n + 1 - elseif p == "G" then - op = op + parse_imm(params[n], 8, 12, 0, false); n = n + 1 - elseif p == "H" then - op = op + parse_shiftmask(params[n], true); n = n + 1 - elseif p == "M" then - op = op + parse_shiftmask(params[n], false); n = n + 1 - elseif p == "J" or p == "K" then - local mode, n, s = parse_label(params[n], false) - if p == "K" then n = n + 2048 end - waction("REL_"..mode, n, s, 1) - n = n + 1 - elseif p == "0" then - if band(shr(op, rs), 31) == 0 then werror("cannot use r0") end - elseif p == "=" or p == "%" then - local t = band(shr(op, p == "%" and rs+5 or rs), 31) - rs = rs - 5 - op = op + shl(t, rs) - elseif p == "~" then - local mm = shl(31, rs) - local lo = band(op, mm) - local hi = band(op, shl(mm, 5)) - op = op - lo - hi + shl(lo, 5) + shr(hi, 5) - elseif p == "-" then - rs = rs - 5 - elseif p == "." then - -- Ignored. - else - assert(false) - end - end - wputpos(pos, op) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode to mark the position where the action list is to be emitted. -map_op[".actionlist_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeactions(out, name) end) -end - --- Pseudo-opcode to mark the position where the global enum is to be emitted. -map_op[".globals_1"] = function(params) - if not params then return "prefix" end - local prefix = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobals(out, prefix) end) -end - --- Pseudo-opcode to mark the position where the global names are to be emitted. -map_op[".globalnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobalnames(out, name) end) -end - --- Pseudo-opcode to mark the position where the extern names are to be emitted. -map_op[".externnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeexternnames(out, name) end) -end - ------------------------------------------------------------------------------- - --- Label pseudo-opcode (converted from trailing colon form). -map_op[".label_1"] = function(params) - if not params then return "[1-9] | ->global | =>pcexpr" end - if secpos+1 > maxsecpos then wflush() end - local mode, n, s = parse_label(params[1], true) - if mode == "EXT" then werror("bad label definition") end - waction("LABEL_"..mode, n, s, 1) -end - ------------------------------------------------------------------------------- - --- Pseudo-opcodes for data storage. -map_op[".long_*"] = function(params) - if not params then return "imm..." end - for _,p in ipairs(params) do - local n = tonumber(p) - if not n then werror("bad immediate `"..p.."'") end - if n < 0 then n = n + 2^32 end - wputw(n) - if secpos+2 > maxsecpos then wflush() end - end -end - --- Alignment pseudo-opcode. -map_op[".align_1"] = function(params) - if not params then return "numpow2" end - if secpos+1 > maxsecpos then wflush() end - local align = tonumber(params[1]) - if align then - local x = align - -- Must be a power of 2 in the range (2 ... 256). - for i=1,8 do - x = x / 2 - if x == 1 then - waction("ALIGN", align-1, nil, 1) -- Action byte is 2**n-1. - return - end - end - end - werror("bad alignment") -end - ------------------------------------------------------------------------------- - --- Pseudo-opcode for (primitive) type definitions (map to C types). -map_op[".type_3"] = function(params, nparams) - if not params then - return nparams == 2 and "name, ctype" or "name, ctype, reg" - end - local name, ctype, reg = params[1], params[2], params[3] - if not match(name, "^[%a_][%w_]*$") then - werror("bad type name `"..name.."'") - end - local tp = map_type[name] - if tp then - werror("duplicate type `"..name.."'") - end - -- Add #type to defines. A bit unclean to put it in map_archdef. - map_archdef["#"..name] = "sizeof("..ctype..")" - -- Add new type and emit shortcut define. - local num = ctypenum + 1 - map_type[name] = { - ctype = ctype, - ctypefmt = format("Dt%X(%%s)", num), - reg = reg, - } - wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) - ctypenum = num -end -map_op[".type_2"] = map_op[".type_3"] - --- Dump type definitions. -local function dumptypes(out, lvl) - local t = {} - for name in pairs(map_type) do t[#t+1] = name end - sort(t) - out:write("Type definitions:\n") - for _,name in ipairs(t) do - local tp = map_type[name] - local reg = tp.reg or "" - out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Set the current section. -function _M.section(num) - waction("SECTION", num) - wflush(true) -- SECTION is a terminal action. -end - ------------------------------------------------------------------------------- - --- Dump architecture description. -function _M.dumparch(out) - out:write(format("DynASM %s version %s, released %s\n\n", - _info.arch, _info.version, _info.release)) - dumpactions(out) -end - --- Dump all user defined elements. -function _M.dumpdef(out, lvl) - dumptypes(out, lvl) - dumpglobals(out, lvl) - dumpexterns(out, lvl) -end - ------------------------------------------------------------------------------- - --- Pass callbacks from/to the DynASM core. -function _M.passcb(wl, we, wf, ww) - wline, werror, wfatal, wwarn = wl, we, wf, ww - return wflush -end - --- Setup the arch-specific module. -function _M.setup(arch, opt) - g_arch, g_opt = arch, opt -end - --- Merge the core maps and the arch-specific maps. -function _M.mergemaps(map_coreop, map_def) - setmetatable(map_op, { __index = map_coreop }) - setmetatable(map_def, { __index = map_archdef }) - return map_op, map_def -end - -return _M - ------------------------------------------------------------------------------- - diff --git a/core/src/luajit/dynasm/dasm_proto.h b/core/src/luajit/dynasm/dasm_proto.h deleted file mode 100644 index a8bc6fd28..000000000 --- a/core/src/luajit/dynasm/dasm_proto.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -** DynASM encoding engine prototypes. -** Copyright (C) 2005-2015 Mike Pall. All rights reserved. -** Released under the MIT license. See dynasm.lua for full copyright notice. -*/ - -#ifndef _DASM_PROTO_H -#define _DASM_PROTO_H - -#include <stddef.h> -#include <stdarg.h> - -#define DASM_IDENT "DynASM 1.3.0" -#define DASM_VERSION 10300 /* 1.3.0 */ - -#ifndef Dst_DECL -#define Dst_DECL dasm_State **Dst -#endif - -#ifndef Dst_REF -#define Dst_REF (*Dst) -#endif - -#ifndef DASM_FDEF -#define DASM_FDEF extern -#endif - -#ifndef DASM_M_GROW -#define DASM_M_GROW(ctx, t, p, sz, need) \ - do { \ - size_t _sz = (sz), _need = (need); \ - if (_sz < _need) { \ - if (_sz < 16) _sz = 16; \ - while (_sz < _need) _sz += _sz; \ - (p) = (t *)realloc((p), _sz); \ - if ((p) == NULL) exit(1); \ - (sz) = _sz; \ - } \ - } while(0) -#endif - -#ifndef DASM_M_FREE -#define DASM_M_FREE(ctx, p, sz) free(p) -#endif - -/* Internal DynASM encoder state. */ -typedef struct dasm_State dasm_State; - - -/* Initialize and free DynASM state. */ -DASM_FDEF void dasm_init(Dst_DECL, int maxsection); -DASM_FDEF void dasm_free(Dst_DECL); - -/* Setup global array. Must be called before dasm_setup(). */ -DASM_FDEF void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl); - -/* Grow PC label array. Can be called after dasm_setup(), too. */ -DASM_FDEF void dasm_growpc(Dst_DECL, unsigned int maxpc); - -/* Setup encoder. */ -DASM_FDEF void dasm_setup(Dst_DECL, const void *actionlist); - -/* Feed encoder with actions. Calls are generated by pre-processor. */ -DASM_FDEF void dasm_put(Dst_DECL, int start, ...); - -/* Link sections and return the resulting size. */ -DASM_FDEF int dasm_link(Dst_DECL, size_t *szp); - -/* Encode sections into buffer. */ -DASM_FDEF int dasm_encode(Dst_DECL, void *buffer); - -/* Get PC label offset. */ -DASM_FDEF int dasm_getpclabel(Dst_DECL, unsigned int pc); - -#ifdef DASM_CHECKS -/* Optional sanity checker to call between isolated encoding steps. */ -DASM_FDEF int dasm_checkstep(Dst_DECL, int secmatch); -#else -#define dasm_checkstep(a, b) 0 -#endif - - -#endif /* _DASM_PROTO_H */ diff --git a/core/src/luajit/dynasm/dasm_x64.lua b/core/src/luajit/dynasm/dasm_x64.lua deleted file mode 100644 index b1b62022f..000000000 --- a/core/src/luajit/dynasm/dasm_x64.lua +++ /dev/null @@ -1,12 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM x64 module. --- --- Copyright (C) 2005-2015 Mike Pall. All rights reserved. --- See dynasm.lua for full copyright notice. ------------------------------------------------------------------------------- --- This module just sets 64 bit mode for the combined x86/x64 module. --- All the interesting stuff is there. ------------------------------------------------------------------------------- - -x64 = true -- Using a global is an ugly, but effective solution. -return require("dasm_x86") diff --git a/core/src/luajit/dynasm/dasm_x86.h b/core/src/luajit/dynasm/dasm_x86.h deleted file mode 100644 index 652e8c99b..000000000 --- a/core/src/luajit/dynasm/dasm_x86.h +++ /dev/null @@ -1,471 +0,0 @@ -/* -** DynASM x86 encoding engine. -** Copyright (C) 2005-2015 Mike Pall. All rights reserved. -** Released under the MIT license. See dynasm.lua for full copyright notice. -*/ - -#include <stddef.h> -#include <stdarg.h> -#include <string.h> -#include <stdlib.h> - -#define DASM_ARCH "x86" - -#ifndef DASM_EXTERN -#define DASM_EXTERN(a,b,c,d) 0 -#endif - -/* Action definitions. DASM_STOP must be 255. */ -enum { - DASM_DISP = 233, - DASM_IMM_S, DASM_IMM_B, DASM_IMM_W, DASM_IMM_D, DASM_IMM_WB, DASM_IMM_DB, - DASM_VREG, DASM_SPACE, DASM_SETLABEL, DASM_REL_A, DASM_REL_LG, DASM_REL_PC, - DASM_IMM_LG, DASM_IMM_PC, DASM_LABEL_LG, DASM_LABEL_PC, DASM_ALIGN, - DASM_EXTERN, DASM_ESC, DASM_MARK, DASM_SECTION, DASM_STOP -}; - -/* Maximum number of section buffer positions for a single dasm_put() call. */ -#define DASM_MAXSECPOS 25 - -/* DynASM encoder status codes. Action list offset or number are or'ed in. */ -#define DASM_S_OK 0x00000000 -#define DASM_S_NOMEM 0x01000000 -#define DASM_S_PHASE 0x02000000 -#define DASM_S_MATCH_SEC 0x03000000 -#define DASM_S_RANGE_I 0x11000000 -#define DASM_S_RANGE_SEC 0x12000000 -#define DASM_S_RANGE_LG 0x13000000 -#define DASM_S_RANGE_PC 0x14000000 -#define DASM_S_RANGE_VREG 0x15000000 -#define DASM_S_UNDEF_L 0x21000000 -#define DASM_S_UNDEF_PC 0x22000000 - -/* Macros to convert positions (8 bit section + 24 bit index). */ -#define DASM_POS2IDX(pos) ((pos)&0x00ffffff) -#define DASM_POS2BIAS(pos) ((pos)&0xff000000) -#define DASM_SEC2POS(sec) ((sec)<<24) -#define DASM_POS2SEC(pos) ((pos)>>24) -#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos)) - -/* Action list type. */ -typedef const unsigned char *dasm_ActList; - -/* Per-section structure. */ -typedef struct dasm_Section { - int *rbuf; /* Biased buffer pointer (negative section bias). */ - int *buf; /* True buffer pointer. */ - size_t bsize; /* Buffer size in bytes. */ - int pos; /* Biased buffer position. */ - int epos; /* End of biased buffer position - max single put. */ - int ofs; /* Byte offset into section. */ -} dasm_Section; - -/* Core structure holding the DynASM encoding state. */ -struct dasm_State { - size_t psize; /* Allocated size of this structure. */ - dasm_ActList actionlist; /* Current actionlist pointer. */ - int *lglabels; /* Local/global chain/pos ptrs. */ - size_t lgsize; - int *pclabels; /* PC label chains/pos ptrs. */ - size_t pcsize; - void **globals; /* Array of globals (bias -10). */ - dasm_Section *section; /* Pointer to active section. */ - size_t codesize; /* Total size of all code sections. */ - int maxsection; /* 0 <= sectionidx < maxsection. */ - int status; /* Status code. */ - dasm_Section sections[1]; /* All sections. Alloc-extended. */ -}; - -/* The size of the core structure depends on the max. number of sections. */ -#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section)) - - -/* Initialize DynASM state. */ -void dasm_init(Dst_DECL, int maxsection) -{ - dasm_State *D; - size_t psz = 0; - int i; - Dst_REF = NULL; - DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection)); - D = Dst_REF; - D->psize = psz; - D->lglabels = NULL; - D->lgsize = 0; - D->pclabels = NULL; - D->pcsize = 0; - D->globals = NULL; - D->maxsection = maxsection; - for (i = 0; i < maxsection; i++) { - D->sections[i].buf = NULL; /* Need this for pass3. */ - D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i); - D->sections[i].bsize = 0; - D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */ - } -} - -/* Free DynASM state. */ -void dasm_free(Dst_DECL) -{ - dasm_State *D = Dst_REF; - int i; - for (i = 0; i < D->maxsection; i++) - if (D->sections[i].buf) - DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize); - if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize); - if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize); - DASM_M_FREE(Dst, D, D->psize); -} - -/* Setup global label array. Must be called before dasm_setup(). */ -void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl) -{ - dasm_State *D = Dst_REF; - D->globals = gl - 10; /* Negative bias to compensate for locals. */ - DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int)); -} - -/* Grow PC label array. Can be called after dasm_setup(), too. */ -void dasm_growpc(Dst_DECL, unsigned int maxpc) -{ - dasm_State *D = Dst_REF; - size_t osz = D->pcsize; - DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int)); - memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz); -} - -/* Setup encoder. */ -void dasm_setup(Dst_DECL, const void *actionlist) -{ - dasm_State *D = Dst_REF; - int i; - D->actionlist = (dasm_ActList)actionlist; - D->status = DASM_S_OK; - D->section = &D->sections[0]; - memset((void *)D->lglabels, 0, D->lgsize); - if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize); - for (i = 0; i < D->maxsection; i++) { - D->sections[i].pos = DASM_SEC2POS(i); - D->sections[i].ofs = 0; - } -} - - -#ifdef DASM_CHECKS -#define CK(x, st) \ - do { if (!(x)) { \ - D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0) -#define CKPL(kind, st) \ - do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \ - D->status=DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0) -#else -#define CK(x, st) ((void)0) -#define CKPL(kind, st) ((void)0) -#endif - -/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ -void dasm_put(Dst_DECL, int start, ...) -{ - va_list ap; - dasm_State *D = Dst_REF; - dasm_ActList p = D->actionlist + start; - dasm_Section *sec = D->section; - int pos = sec->pos, ofs = sec->ofs, mrm = 4; - int *b; - - if (pos >= sec->epos) { - DASM_M_GROW(Dst, int, sec->buf, sec->bsize, - sec->bsize + 2*DASM_MAXSECPOS*sizeof(int)); - sec->rbuf = sec->buf - DASM_POS2BIAS(pos); - sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos); - } - - b = sec->rbuf; - b[pos++] = start; - - va_start(ap, start); - while (1) { - int action = *p++; - if (action < DASM_DISP) { - ofs++; - } else if (action <= DASM_REL_A) { - int n = va_arg(ap, int); - b[pos++] = n; - switch (action) { - case DASM_DISP: - if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; } - case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob; - case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */ - case DASM_IMM_D: ofs += 4; break; - case DASM_IMM_S: CK(((n+128)&-256) == 0, RANGE_I); goto ob; - case DASM_IMM_B: CK((n&-256) == 0, RANGE_I); ob: ofs++; break; - case DASM_IMM_WB: if (((n+128)&-256) == 0) goto ob; - case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break; - case DASM_SPACE: p++; ofs += n; break; - case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */ - case DASM_VREG: CK((n&-8) == 0 && (n != 4 || (*p&1) == 0), RANGE_VREG); - if (*p++ == 1 && *p == DASM_DISP) mrm = n; continue; - } - mrm = 4; - } else { - int *pl, n; - switch (action) { - case DASM_REL_LG: - case DASM_IMM_LG: - n = *p++; pl = D->lglabels + n; - /* Bkwd rel or global. */ - if (n <= 246) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; } - pl -= 246; n = *pl; - if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */ - goto linkrel; - case DASM_REL_PC: - case DASM_IMM_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); - putrel: - n = *pl; - if (n < 0) { /* Label exists. Get label pos and store it. */ - b[pos] = -n; - } else { - linkrel: - b[pos] = n; /* Else link to rel chain, anchored at label. */ - *pl = pos; - } - pos++; - ofs += 4; /* Maximum offset needed. */ - if (action == DASM_REL_LG || action == DASM_REL_PC) - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel; - case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); - putlabel: - n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos; } - *pl = -pos; /* Label exists now. */ - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_ALIGN: - ofs += *p++; /* Maximum alignment needed (arg is 2**n-1). */ - b[pos++] = ofs; /* Store pass1 offset estimate. */ - break; - case DASM_EXTERN: p += 2; ofs += 4; break; - case DASM_ESC: p++; ofs++; break; - case DASM_MARK: mrm = p[-2]; break; - case DASM_SECTION: - n = *p; CK(n < D->maxsection, RANGE_SEC); D->section = &D->sections[n]; - case DASM_STOP: goto stop; - } - } - } -stop: - va_end(ap); - sec->pos = pos; - sec->ofs = ofs; -} -#undef CK - -/* Pass 2: Link sections, shrink branches/aligns, fix label offsets. */ -int dasm_link(Dst_DECL, size_t *szp) -{ - dasm_State *D = Dst_REF; - int secnum; - int ofs = 0; - -#ifdef DASM_CHECKS - *szp = 0; - if (D->status != DASM_S_OK) return D->status; - { - int pc; - for (pc = 0; pc*sizeof(int) < D->pcsize; pc++) - if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc; - } -#endif - - { /* Handle globals not defined in this translation unit. */ - int idx; - for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) { - int n = D->lglabels[idx]; - /* Undefined label: Collapse rel chain and replace with marker (< 0). */ - while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } - } - } - - /* Combine all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->rbuf; - int pos = DASM_SEC2POS(secnum); - int lastpos = sec->pos; - - while (pos != lastpos) { - dasm_ActList p = D->actionlist + b[pos++]; - while (1) { - int op, action = *p++; - switch (action) { - case DASM_REL_LG: p++; op = p[-3]; goto rel_pc; - case DASM_REL_PC: op = p[-2]; rel_pc: { - int shrink = op == 0xe9 ? 3 : ((op&0xf0) == 0x80 ? 4 : 0); - if (shrink) { /* Shrinkable branch opcode? */ - int lofs, lpos = b[pos]; - if (lpos < 0) goto noshrink; /* Ext global? */ - lofs = *DASM_POS2PTR(D, lpos); - if (lpos > pos) { /* Fwd label: add cumulative section offsets. */ - int i; - for (i = secnum; i < DASM_POS2SEC(lpos); i++) - lofs += D->sections[i].ofs; - } else { - lofs -= ofs; /* Bkwd label: unfix offset. */ - } - lofs -= b[pos+1]; /* Short branch ok? */ - if (lofs >= -128-shrink && lofs <= 127) ofs -= shrink; /* Yes. */ - else { noshrink: shrink = 0; } /* No, cannot shrink op. */ - } - b[pos+1] = shrink; - pos += 2; - break; - } - case DASM_SPACE: case DASM_IMM_LG: case DASM_VREG: p++; - case DASM_DISP: case DASM_IMM_S: case DASM_IMM_B: case DASM_IMM_W: - case DASM_IMM_D: case DASM_IMM_WB: case DASM_IMM_DB: - case DASM_SETLABEL: case DASM_REL_A: case DASM_IMM_PC: pos++; break; - case DASM_LABEL_LG: p++; - case DASM_LABEL_PC: b[pos++] += ofs; break; /* Fix label offset. */ - case DASM_ALIGN: ofs -= (b[pos++]+ofs)&*p++; break; /* Adjust ofs. */ - case DASM_EXTERN: p += 2; break; - case DASM_ESC: p++; break; - case DASM_MARK: break; - case DASM_SECTION: case DASM_STOP: goto stop; - } - } - stop: (void)0; - } - ofs += sec->ofs; /* Next section starts right after current section. */ - } - - D->codesize = ofs; /* Total size of all code sections */ - *szp = ofs; - return DASM_S_OK; -} - -#define dasmb(x) *cp++ = (unsigned char)(x) -#ifndef DASM_ALIGNED_WRITES -#define dasmw(x) \ - do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) -#define dasmd(x) \ - do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0) -#else -#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) -#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) -#endif - -/* Pass 3: Encode sections. */ -int dasm_encode(Dst_DECL, void *buffer) -{ - dasm_State *D = Dst_REF; - unsigned char *base = (unsigned char *)buffer; - unsigned char *cp = base; - int secnum; - - /* Encode all code sections. No support for data sections (yet). */ - for (secnum = 0; secnum < D->maxsection; secnum++) { - dasm_Section *sec = D->sections + secnum; - int *b = sec->buf; - int *endb = sec->rbuf + sec->pos; - - while (b != endb) { - dasm_ActList p = D->actionlist + *b++; - unsigned char *mark = NULL; - while (1) { - int action = *p++; - int n = (action >= DASM_DISP && action <= DASM_ALIGN) ? *b++ : 0; - switch (action) { - case DASM_DISP: if (!mark) mark = cp; { - unsigned char *mm = mark; - if (*p != DASM_IMM_DB && *p != DASM_IMM_WB) mark = NULL; - if (n == 0) { int mrm = mm[-1]&7; if (mrm == 4) mrm = mm[0]&7; - if (mrm != 5) { mm[-1] -= 0x80; break; } } - if (((n+128) & -256) != 0) goto wd; else mm[-1] -= 0x40; - } - case DASM_IMM_S: case DASM_IMM_B: wb: dasmb(n); break; - case DASM_IMM_DB: if (((n+128)&-256) == 0) { - db: if (!mark) mark = cp; mark[-2] += 2; mark = NULL; goto wb; - } else mark = NULL; - case DASM_IMM_D: wd: dasmd(n); break; - case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL; - case DASM_IMM_W: dasmw(n); break; - case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; } - case DASM_REL_LG: p++; if (n >= 0) goto rel_pc; - b++; n = (int)(ptrdiff_t)D->globals[-n]; - case DASM_REL_A: rel_a: n -= (int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */ - case DASM_REL_PC: rel_pc: { - int shrink = *b++; - int *pb = DASM_POS2PTR(D, n); if (*pb < 0) { n = pb[1]; goto rel_a; } - n = *pb - ((int)(cp-base) + 4-shrink); - if (shrink == 0) goto wd; - if (shrink == 4) { cp--; cp[-1] = *cp-0x10; } else cp[-1] = 0xeb; - goto wb; - } - case DASM_IMM_LG: - p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; } - case DASM_IMM_PC: { - int *pb = DASM_POS2PTR(D, n); - n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); - goto wd; - } - case DASM_LABEL_LG: { - int idx = *p++; - if (idx >= 10) - D->globals[idx] = (void *)(base + (*p == DASM_SETLABEL ? *b : n)); - break; - } - case DASM_LABEL_PC: case DASM_SETLABEL: break; - case DASM_SPACE: { int fill = *p++; while (n--) *cp++ = fill; break; } - case DASM_ALIGN: - n = *p++; - while (((cp-base) & n)) *cp++ = 0x90; /* nop */ - break; - case DASM_EXTERN: n = DASM_EXTERN(Dst, cp, p[1], *p); p += 2; goto wd; - case DASM_MARK: mark = cp; break; - case DASM_ESC: action = *p++; - default: *cp++ = action; break; - case DASM_SECTION: case DASM_STOP: goto stop; - } - } - stop: (void)0; - } - } - - if (base + D->codesize != cp) /* Check for phase errors. */ - return DASM_S_PHASE; - return DASM_S_OK; -} - -/* Get PC label offset. */ -int dasm_getpclabel(Dst_DECL, unsigned int pc) -{ - dasm_State *D = Dst_REF; - if (pc*sizeof(int) < D->pcsize) { - int pos = D->pclabels[pc]; - if (pos < 0) return *DASM_POS2PTR(D, -pos); - if (pos > 0) return -1; /* Undefined. */ - } - return -2; /* Unused or out of range. */ -} - -#ifdef DASM_CHECKS -/* Optional sanity checker to call between isolated encoding steps. */ -int dasm_checkstep(Dst_DECL, int secmatch) -{ - dasm_State *D = Dst_REF; - if (D->status == DASM_S_OK) { - int i; - for (i = 1; i <= 9; i++) { - if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_L|i; break; } - D->lglabels[i] = 0; - } - } - if (D->status == DASM_S_OK && secmatch >= 0 && - D->section != &D->sections[secmatch]) - D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections); - return D->status; -} -#endif - diff --git a/core/src/luajit/dynasm/dasm_x86.lua b/core/src/luajit/dynasm/dasm_x86.lua deleted file mode 100644 index 7ca061d22..000000000 --- a/core/src/luajit/dynasm/dasm_x86.lua +++ /dev/null @@ -1,1945 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM x86/x64 module. --- --- Copyright (C) 2005-2015 Mike Pall. All rights reserved. --- See dynasm.lua for full copyright notice. ------------------------------------------------------------------------------- - -local x64 = x64 - --- Module information: -local _info = { - arch = x64 and "x64" or "x86", - description = "DynASM x86/x64 module", - version = "1.3.0", - vernum = 10300, - release = "2011-05-05", - author = "Mike Pall", - license = "MIT", -} - --- Exported glue functions for the arch-specific module. -local _M = { _info = _info } - --- Cache library functions. -local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs -local assert, unpack, setmetatable = assert, unpack or table.unpack, setmetatable -local _s = string -local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char -local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub -local concat, sort = table.concat, table.sort -local bit = bit or require("bit") -local band, shl, shr = bit.band, bit.lshift, bit.rshift - --- Inherited tables and callbacks. -local g_opt, g_arch -local wline, werror, wfatal, wwarn - --- Action name list. --- CHECK: Keep this in sync with the C code! -local action_names = { - -- int arg, 1 buffer pos: - "DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB", - -- action arg (1 byte), int arg, 1 buffer pos (reg/num): - "VREG", "SPACE", -- !x64: VREG support NYI. - -- ptrdiff_t arg, 1 buffer pos (address): !x64 - "SETLABEL", "REL_A", - -- action arg (1 byte) or int arg, 2 buffer pos (link, offset): - "REL_LG", "REL_PC", - -- action arg (1 byte) or int arg, 1 buffer pos (link): - "IMM_LG", "IMM_PC", - -- action arg (1 byte) or int arg, 1 buffer pos (offset): - "LABEL_LG", "LABEL_PC", - -- action arg (1 byte), 1 buffer pos (offset): - "ALIGN", - -- action args (2 bytes), no buffer pos. - "EXTERN", - -- action arg (1 byte), no buffer pos. - "ESC", - -- no action arg, no buffer pos. - "MARK", - -- action arg (1 byte), no buffer pos, terminal action: - "SECTION", - -- no args, no buffer pos, terminal action: - "STOP" -} - --- Maximum number of section buffer positions for dasm_put(). --- CHECK: Keep this in sync with the C code! -local maxsecpos = 25 -- Keep this low, to avoid excessively long C lines. - --- Action name -> action number (dynamically generated below). -local map_action = {} --- First action number. Everything below does not need to be escaped. -local actfirst = 256-#action_names - --- Action list buffer and string (only used to remove dupes). -local actlist = {} -local actstr = "" - --- Argument list for next dasm_put(). Start with offset 0 into action list. -local actargs = { 0 } - --- Current number of section buffer positions for dasm_put(). -local secpos = 1 - ------------------------------------------------------------------------------- - --- Compute action numbers for action names. -for n,name in ipairs(action_names) do - local num = actfirst + n - 1 - map_action[name] = num -end - --- Dump action names and numbers. -local function dumpactions(out) - out:write("DynASM encoding engine action codes:\n") - for n,name in ipairs(action_names) do - local num = map_action[name] - out:write(format(" %-10s %02X %d\n", name, num, num)) - end - out:write("\n") -end - --- Write action list buffer as a huge static C array. -local function writeactions(out, name) - local nn = #actlist - local last = actlist[nn] or 255 - actlist[nn] = nil -- Remove last byte. - if nn == 0 then nn = 1 end - out:write("static const unsigned char ", name, "[", nn, "] = {\n") - local s = " " - for n,b in ipairs(actlist) do - s = s..b.."," - if #s >= 75 then - assert(out:write(s, "\n")) - s = " " - end - end - out:write(s, last, "\n};\n\n") -- Add last byte back. -end - ------------------------------------------------------------------------------- - --- Add byte to action list. -local function wputxb(n) - assert(n >= 0 and n <= 255 and n % 1 == 0, "byte out of range") - actlist[#actlist+1] = n -end - --- Add action to list with optional arg. Advance buffer pos, too. -local function waction(action, a, num) - wputxb(assert(map_action[action], "bad action name `"..action.."'")) - if a then actargs[#actargs+1] = a end - if a or num then secpos = secpos + (num or 1) end -end - --- Add call to embedded DynASM C code. -local function wcall(func, args) - wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true) -end - --- Delete duplicate action list chunks. A tad slow, but so what. -local function dedupechunk(offset) - local al, as = actlist, actstr - local chunk = char(unpack(al, offset+1, #al)) - local orig = find(as, chunk, 1, true) - if orig then - actargs[1] = orig-1 -- Replace with original offset. - for i=offset+1,#al do al[i] = nil end -- Kill dupe. - else - actstr = as..chunk - end -end - --- Flush action list (intervening C code or buffer pos overflow). -local function wflush(term) - local offset = actargs[1] - if #actlist == offset then return end -- Nothing to flush. - if not term then waction("STOP") end -- Terminate action list. - dedupechunk(offset) - wcall("put", actargs) -- Add call to dasm_put(). - actargs = { #actlist } -- Actionlist offset is 1st arg to next dasm_put(). - secpos = 1 -- The actionlist offset occupies a buffer position, too. -end - --- Put escaped byte. -local function wputb(n) - if n >= actfirst then waction("ESC") end -- Need to escape byte. - wputxb(n) -end - ------------------------------------------------------------------------------- - --- Global label name -> global label number. With auto assignment on 1st use. -local next_global = 10 -local map_global = setmetatable({}, { __index = function(t, name) - if not match(name, "^[%a_][%w_@]*$") then werror("bad global label") end - local n = next_global - if n > 246 then werror("too many global labels") end - next_global = n + 1 - t[name] = n - return n -end}) - --- Dump global labels. -local function dumpglobals(out, lvl) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("Global labels:\n") - for i=10,next_global-1 do - out:write(format(" %s\n", t[i])) - end - out:write("\n") -end - --- Write global label enum. -local function writeglobals(out, prefix) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("enum {\n") - for i=10,next_global-1 do - out:write(" ", prefix, gsub(t[i], "@.*", ""), ",\n") - end - out:write(" ", prefix, "_MAX\n};\n") -end - --- Write global label names. -local function writeglobalnames(out, name) - local t = {} - for name, n in pairs(map_global) do t[n] = name end - out:write("static const char *const ", name, "[] = {\n") - for i=10,next_global-1 do - out:write(" \"", t[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Extern label name -> extern label number. With auto assignment on 1st use. -local next_extern = -1 -local map_extern = setmetatable({}, { __index = function(t, name) - -- No restrictions on the name for now. - local n = next_extern - if n < -256 then werror("too many extern labels") end - next_extern = n - 1 - t[name] = n - return n -end}) - --- Dump extern labels. -local function dumpexterns(out, lvl) - local t = {} - for name, n in pairs(map_extern) do t[-n] = name end - out:write("Extern labels:\n") - for i=1,-next_extern-1 do - out:write(format(" %s\n", t[i])) - end - out:write("\n") -end - --- Write extern label names. -local function writeexternnames(out, name) - local t = {} - for name, n in pairs(map_extern) do t[-n] = name end - out:write("static const char *const ", name, "[] = {\n") - for i=1,-next_extern-1 do - out:write(" \"", t[i], "\",\n") - end - out:write(" (const char *)0\n};\n") -end - ------------------------------------------------------------------------------- - --- Arch-specific maps. -local map_archdef = {} -- Ext. register name -> int. name. -local map_reg_rev = {} -- Int. register name -> ext. name. -local map_reg_num = {} -- Int. register name -> register number. -local map_reg_opsize = {} -- Int. register name -> operand size. -local map_reg_valid_base = {} -- Int. register name -> valid base register? -local map_reg_valid_index = {} -- Int. register name -> valid index register? -local map_reg_needrex = {} -- Int. register name -> need rex vs. no rex. -local reg_list = {} -- Canonical list of int. register names. - -local map_type = {} -- Type name -> { ctype, reg } -local ctypenum = 0 -- Type number (for _PTx macros). - -local addrsize = x64 and "q" or "d" -- Size for address operands. - --- Helper functions to fill register maps. -local function mkrmap(sz, cl, names) - local cname = format("@%s", sz) - reg_list[#reg_list+1] = cname - map_archdef[cl] = cname - map_reg_rev[cname] = cl - map_reg_num[cname] = -1 - map_reg_opsize[cname] = sz - if sz == addrsize or sz == "d" then - map_reg_valid_base[cname] = true - map_reg_valid_index[cname] = true - end - if names then - for n,name in ipairs(names) do - local iname = format("@%s%x", sz, n-1) - reg_list[#reg_list+1] = iname - map_archdef[name] = iname - map_reg_rev[iname] = name - map_reg_num[iname] = n-1 - map_reg_opsize[iname] = sz - if sz == "b" and n > 4 then map_reg_needrex[iname] = false end - if sz == addrsize or sz == "d" then - map_reg_valid_base[iname] = true - map_reg_valid_index[iname] = true - end - end - end - for i=0,(x64 and sz ~= "f") and 15 or 7 do - local needrex = sz == "b" and i > 3 - local iname = format("@%s%x%s", sz, i, needrex and "R" or "") - if needrex then map_reg_needrex[iname] = true end - local name - if sz == "o" then name = format("xmm%d", i) - elseif sz == "f" then name = format("st%d", i) - else name = format("r%d%s", i, sz == addrsize and "" or sz) end - map_archdef[name] = iname - if not map_reg_rev[iname] then - reg_list[#reg_list+1] = iname - map_reg_rev[iname] = name - map_reg_num[iname] = i - map_reg_opsize[iname] = sz - if sz == addrsize or sz == "d" then - map_reg_valid_base[iname] = true - map_reg_valid_index[iname] = true - end - end - end - reg_list[#reg_list+1] = "" -end - --- Integer registers (qword, dword, word and byte sized). -if x64 then - mkrmap("q", "Rq", {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"}) -end -mkrmap("d", "Rd", {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}) -mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"}) -mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}) -map_reg_valid_index[map_archdef.esp] = false -if x64 then map_reg_valid_index[map_archdef.rsp] = false end -map_archdef["Ra"] = "@"..addrsize - --- FP registers (internally tword sized, but use "f" as operand size). -mkrmap("f", "Rf") - --- SSE registers (oword sized, but qword and dword accessible). -mkrmap("o", "xmm") - --- Operand size prefixes to codes. -local map_opsize = { - byte = "b", word = "w", dword = "d", qword = "q", oword = "o", tword = "t", - aword = addrsize, -} - --- Operand size code to number. -local map_opsizenum = { - b = 1, w = 2, d = 4, q = 8, o = 16, t = 10, -} - --- Operand size code to name. -local map_opsizename = { - b = "byte", w = "word", d = "dword", q = "qword", o = "oword", t = "tword", - f = "fpword", -} - --- Valid index register scale factors. -local map_xsc = { - ["1"] = 0, ["2"] = 1, ["4"] = 2, ["8"] = 3, -} - --- Condition codes. -local map_cc = { - o = 0, no = 1, b = 2, nb = 3, e = 4, ne = 5, be = 6, nbe = 7, - s = 8, ns = 9, p = 10, np = 11, l = 12, nl = 13, le = 14, nle = 15, - c = 2, nae = 2, nc = 3, ae = 3, z = 4, nz = 5, na = 6, a = 7, - pe = 10, po = 11, nge = 12, ge = 13, ng = 14, g = 15, -} - - --- Reverse defines for registers. -function _M.revdef(s) - return gsub(s, "@%w+", map_reg_rev) -end - --- Dump register names and numbers -local function dumpregs(out) - out:write("Register names, sizes and internal numbers:\n") - for _,reg in ipairs(reg_list) do - if reg == "" then - out:write("\n") - else - local name = map_reg_rev[reg] - local num = map_reg_num[reg] - local opsize = map_opsizename[map_reg_opsize[reg]] - out:write(format(" %-5s %-8s %s\n", name, opsize, - num < 0 and "(variable)" or num)) - end - end -end - ------------------------------------------------------------------------------- - --- Put action for label arg (IMM_LG, IMM_PC, REL_LG, REL_PC). -local function wputlabel(aprefix, imm, num) - if type(imm) == "number" then - if imm < 0 then - waction("EXTERN") - wputxb(aprefix == "IMM_" and 0 or 1) - imm = -imm-1 - else - waction(aprefix.."LG", nil, num); - end - wputxb(imm) - else - waction(aprefix.."PC", imm, num) - end -end - --- Put signed byte or arg. -local function wputsbarg(n) - if type(n) == "number" then - if n < -128 or n > 127 then - werror("signed immediate byte out of range") - end - if n < 0 then n = n + 256 end - wputb(n) - else waction("IMM_S", n) end -end - --- Put unsigned byte or arg. -local function wputbarg(n) - if type(n) == "number" then - if n < 0 or n > 255 then - werror("unsigned immediate byte out of range") - end - wputb(n) - else waction("IMM_B", n) end -end - --- Put unsigned word or arg. -local function wputwarg(n) - if type(n) == "number" then - if shr(n, 16) ~= 0 then - werror("unsigned immediate word out of range") - end - wputb(band(n, 255)); wputb(shr(n, 8)); - else waction("IMM_W", n) end -end - --- Put signed or unsigned dword or arg. -local function wputdarg(n) - local tn = type(n) - if tn == "number" then - wputb(band(n, 255)) - wputb(band(shr(n, 8), 255)) - wputb(band(shr(n, 16), 255)) - wputb(shr(n, 24)) - elseif tn == "table" then - wputlabel("IMM_", n[1], 1) - else - waction("IMM_D", n) - end -end - --- Put operand-size dependent number or arg (defaults to dword). -local function wputszarg(sz, n) - if not sz or sz == "d" or sz == "q" then wputdarg(n) - elseif sz == "w" then wputwarg(n) - elseif sz == "b" then wputbarg(n) - elseif sz == "s" then wputsbarg(n) - else werror("bad operand size") end -end - --- Put multi-byte opcode with operand-size dependent modifications. -local function wputop(sz, op, rex) - local r - if rex ~= 0 and not x64 then werror("bad operand size") end - if sz == "w" then wputb(102) end - -- Needs >32 bit numbers, but only for crc32 eax, word [ebx] - if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end - if op >= 16777216 then wputb(shr(op, 24)); op = band(op, 0xffffff) end - if op >= 65536 then - if rex ~= 0 then - local opc3 = band(op, 0xffff00) - if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then - wputb(64 + band(rex, 15)); rex = 0 - end - end - wputb(shr(op, 16)); op = band(op, 0xffff) - end - if op >= 256 then - local b = shr(op, 8) - if b == 15 and rex ~= 0 then wputb(64 + band(rex, 15)); rex = 0 end - wputb(b) - op = band(op, 255) - end - if rex ~= 0 then wputb(64 + band(rex, 15)) end - if sz == "b" then op = op - 1 end - wputb(op) -end - --- Put ModRM or SIB formatted byte. -local function wputmodrm(m, s, rm, vs, vrm) - assert(m < 4 and s < 16 and rm < 16, "bad modrm operands") - wputb(shl(m, 6) + shl(band(s, 7), 3) + band(rm, 7)) -end - --- Put ModRM/SIB plus optional displacement. -local function wputmrmsib(t, imark, s, vsreg) - local vreg, vxreg - local reg, xreg = t.reg, t.xreg - if reg and reg < 0 then reg = 0; vreg = t.vreg end - if xreg and xreg < 0 then xreg = 0; vxreg = t.vxreg end - if s < 0 then s = 0 end - - -- Register mode. - if sub(t.mode, 1, 1) == "r" then - wputmodrm(3, s, reg) - if vsreg then waction("VREG", vsreg); wputxb(2) end - if vreg then waction("VREG", vreg); wputxb(0) end - return - end - - local disp = t.disp - local tdisp = type(disp) - -- No base register? - if not reg then - local riprel = false - if xreg then - -- Indexed mode with index register only. - -- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp) - wputmodrm(0, s, 4) - if imark == "I" then waction("MARK") end - if vsreg then waction("VREG", vsreg); wputxb(2) end - wputmodrm(t.xsc, xreg, 5) - if vxreg then waction("VREG", vxreg); wputxb(3) end - else - -- Pure 32 bit displacement. - if x64 and tdisp ~= "table" then - wputmodrm(0, s, 4) -- [disp] -> (0, s, esp) (0, esp, ebp) - if imark == "I" then waction("MARK") end - wputmodrm(0, 4, 5) - else - riprel = x64 - wputmodrm(0, s, 5) -- [disp|rip-label] -> (0, s, ebp) - if imark == "I" then waction("MARK") end - end - if vsreg then waction("VREG", vsreg); wputxb(2) end - end - if riprel then -- Emit rip-relative displacement. - if match("UWSiI", imark) then - werror("NYI: rip-relative displacement followed by immediate") - end - -- The previous byte in the action buffer cannot be 0xe9 or 0x80-0x8f. - wputlabel("REL_", disp[1], 2) - else - wputdarg(disp) - end - return - end - - local m - if tdisp == "number" then -- Check displacement size at assembly time. - if disp == 0 and band(reg, 7) ~= 5 then -- [ebp] -> [ebp+0] (in SIB, too) - if not vreg then m = 0 end -- Force DISP to allow [Rd(5)] -> [ebp+0] - elseif disp >= -128 and disp <= 127 then m = 1 - else m = 2 end - elseif tdisp == "table" then - m = 2 - end - - -- Index register present or esp as base register: need SIB encoding. - if xreg or band(reg, 7) == 4 then - wputmodrm(m or 2, s, 4) -- ModRM. - if m == nil or imark == "I" then waction("MARK") end - if vsreg then waction("VREG", vsreg); wputxb(2) end - wputmodrm(t.xsc or 0, xreg or 4, reg) -- SIB. - if vxreg then waction("VREG", vxreg); wputxb(3) end - if vreg then waction("VREG", vreg); wputxb(1) end - else - wputmodrm(m or 2, s, reg) -- ModRM. - if (imark == "I" and (m == 1 or m == 2)) or - (m == nil and (vsreg or vreg)) then waction("MARK") end - if vsreg then waction("VREG", vsreg); wputxb(2) end - if vreg then waction("VREG", vreg); wputxb(1) end - end - - -- Put displacement. - if m == 1 then wputsbarg(disp) - elseif m == 2 then wputdarg(disp) - elseif m == nil then waction("DISP", disp) end -end - ------------------------------------------------------------------------------- - --- Return human-readable operand mode string. -local function opmodestr(op, args) - local m = {} - for i=1,#args do - local a = args[i] - m[#m+1] = sub(a.mode, 1, 1)..(a.opsize or "?") - end - return op.." "..concat(m, ",") -end - --- Convert number to valid integer or nil. -local function toint(expr) - local n = tonumber(expr) - if n then - if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then - werror("bad integer number `"..expr.."'") - end - return n - end -end - --- Parse immediate expression. -local function immexpr(expr) - -- &expr (pointer) - if sub(expr, 1, 1) == "&" then - return "iPJ", format("(ptrdiff_t)(%s)", sub(expr,2)) - end - - local prefix = sub(expr, 1, 2) - -- =>expr (pc label reference) - if prefix == "=>" then - return "iJ", sub(expr, 3) - end - -- ->name (global label reference) - if prefix == "->" then - return "iJ", map_global[sub(expr, 3)] - end - - -- [<>][1-9] (local label reference) - local dir, lnum = match(expr, "^([<>])([1-9])$") - if dir then -- Fwd: 247-255, Bkwd: 1-9. - return "iJ", lnum + (dir == ">" and 246 or 0) - end - - local extname = match(expr, "^extern%s+(%S+)$") - if extname then - return "iJ", map_extern[extname] - end - - -- expr (interpreted as immediate) - return "iI", expr -end - --- Parse displacement expression: +-num, +-expr, +-opsize*num -local function dispexpr(expr) - local disp = expr == "" and 0 or toint(expr) - if disp then return disp end - local c, dispt = match(expr, "^([+-])%s*(.+)$") - if c == "+" then - expr = dispt - elseif not c then - werror("bad displacement expression `"..expr.."'") - end - local opsize, tailops = match(dispt, "^(%w+)%s*%*%s*(.+)$") - local ops, imm = map_opsize[opsize], toint(tailops) - if ops and imm then - if c == "-" then imm = -imm end - return imm*map_opsizenum[ops] - end - local mode, iexpr = immexpr(dispt) - if mode == "iJ" then - if c == "-" then werror("cannot invert label reference") end - return { iexpr } - end - return expr -- Need to return original signed expression. -end - --- Parse register or type expression. -local function rtexpr(expr) - if not expr then return end - local tname, ovreg = match(expr, "^([%w_]+):(@[%w_]+)$") - local tp = map_type[tname or expr] - if tp then - local reg = ovreg or tp.reg - local rnum = map_reg_num[reg] - if not rnum then - werror("type `"..(tname or expr).."' needs a register override") - end - if not map_reg_valid_base[reg] then - werror("bad base register override `"..(map_reg_rev[reg] or reg).."'") - end - return reg, rnum, tp - end - return expr, map_reg_num[expr] -end - --- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }. -local function parseoperand(param) - local t = {} - - local expr = param - local opsize, tailops = match(param, "^(%w+)%s*(.+)$") - if opsize then - t.opsize = map_opsize[opsize] - if t.opsize then expr = tailops end - end - - local br = match(expr, "^%[%s*(.-)%s*%]$") - repeat - if br then - t.mode = "xm" - - -- [disp] - t.disp = toint(br) - if t.disp then - t.mode = x64 and "xm" or "xmO" - break - end - - -- [reg...] - local tp - local reg, tailr = match(br, "^([@%w_:]+)%s*(.*)$") - reg, t.reg, tp = rtexpr(reg) - if not t.reg then - -- [expr] - t.mode = x64 and "xm" or "xmO" - t.disp = dispexpr("+"..br) - break - end - - if t.reg == -1 then - t.vreg, tailr = match(tailr, "^(%b())(.*)$") - if not t.vreg then werror("bad variable register expression") end - end - - -- [xreg*xsc] or [xreg*xsc+-disp] or [xreg*xsc+-expr] - local xsc, tailsc = match(tailr, "^%*%s*([1248])%s*(.*)$") - if xsc then - if not map_reg_valid_index[reg] then - werror("bad index register `"..map_reg_rev[reg].."'") - end - t.xsc = map_xsc[xsc] - t.xreg = t.reg - t.vxreg = t.vreg - t.reg = nil - t.vreg = nil - t.disp = dispexpr(tailsc) - break - end - if not map_reg_valid_base[reg] then - werror("bad base register `"..map_reg_rev[reg].."'") - end - - -- [reg] or [reg+-disp] - t.disp = toint(tailr) or (tailr == "" and 0) - if t.disp then break end - - -- [reg+xreg...] - local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$") - xreg, t.xreg, tp = rtexpr(xreg) - if not t.xreg then - -- [reg+-expr] - t.disp = dispexpr(tailr) - break - end - if not map_reg_valid_index[xreg] then - werror("bad index register `"..map_reg_rev[xreg].."'") - end - - if t.xreg == -1 then - t.vxreg, tailx = match(tailx, "^(%b())(.*)$") - if not t.vxreg then werror("bad variable register expression") end - end - - -- [reg+xreg*xsc...] - local xsc, tailsc = match(tailx, "^%*%s*([1248])%s*(.*)$") - if xsc then - t.xsc = map_xsc[xsc] - tailx = tailsc - end - - -- [...] or [...+-disp] or [...+-expr] - t.disp = dispexpr(tailx) - else - -- imm or opsize*imm - local imm = toint(expr) - if not imm and sub(expr, 1, 1) == "*" and t.opsize then - imm = toint(sub(expr, 2)) - if imm then - imm = imm * map_opsizenum[t.opsize] - t.opsize = nil - end - end - if imm then - if t.opsize then werror("bad operand size override") end - local m = "i" - if imm == 1 then m = m.."1" end - if imm >= 4294967168 and imm <= 4294967295 then imm = imm-4294967296 end - if imm >= -128 and imm <= 127 then m = m.."S" end - t.imm = imm - t.mode = m - break - end - - local tp - local reg, tailr = match(expr, "^([@%w_:]+)%s*(.*)$") - reg, t.reg, tp = rtexpr(reg) - if t.reg then - if t.reg == -1 then - t.vreg, tailr = match(tailr, "^(%b())(.*)$") - if not t.vreg then werror("bad variable register expression") end - end - -- reg - if tailr == "" then - if t.opsize then werror("bad operand size override") end - t.opsize = map_reg_opsize[reg] - if t.opsize == "f" then - t.mode = t.reg == 0 and "fF" or "f" - else - if reg == "@w4" or (x64 and reg == "@d4") then - wwarn("bad idea, try again with `"..(x64 and "rsp'" or "esp'")) - end - t.mode = t.reg == 0 and "rmR" or (reg == "@b1" and "rmC" or "rm") - end - t.needrex = map_reg_needrex[reg] - break - end - - -- type[idx], type[idx].field, type->field -> [reg+offset_expr] - if not tp then werror("bad operand `"..param.."'") end - t.mode = "xm" - t.disp = format(tp.ctypefmt, tailr) - else - t.mode, t.imm = immexpr(expr) - if sub(t.mode, -1) == "J" then - if t.opsize and t.opsize ~= addrsize then - werror("bad operand size override") - end - t.opsize = addrsize - end - end - end - until true - return t -end - ------------------------------------------------------------------------------- --- x86 Template String Description --- =============================== --- --- Each template string is a list of [match:]pattern pairs, --- separated by "|". The first match wins. No match means a --- bad or unsupported combination of operand modes or sizes. --- --- The match part and the ":" is omitted if the operation has --- no operands. Otherwise the first N characters are matched --- against the mode strings of each of the N operands. --- --- The mode string for each operand type is (see parseoperand()): --- Integer register: "rm", +"R" for eax, ax, al, +"C" for cl --- FP register: "f", +"F" for st0 --- Index operand: "xm", +"O" for [disp] (pure offset) --- Immediate: "i", +"S" for signed 8 bit, +"1" for 1, --- +"I" for arg, +"P" for pointer --- Any: +"J" for valid jump targets --- --- So a match character "m" (mixed) matches both an integer register --- and an index operand (to be encoded with the ModRM/SIB scheme). --- But "r" matches only a register and "x" only an index operand --- (e.g. for FP memory access operations). --- --- The operand size match string starts right after the mode match --- characters and ends before the ":". "dwb" or "qdwb" is assumed, if empty. --- The effective data size of the operation is matched against this list. --- --- If only the regular "b", "w", "d", "q", "t" operand sizes are --- present, then all operands must be the same size. Unspecified sizes --- are ignored, but at least one operand must have a size or the pattern --- won't match (use the "byte", "word", "dword", "qword", "tword" --- operand size overrides. E.g.: mov dword [eax], 1). --- --- If the list has a "1" or "2" prefix, the operand size is taken --- from the respective operand and any other operand sizes are ignored. --- If the list contains only ".", all operand sizes are ignored. --- If the list has a "/" prefix, the concatenated (mixed) operand sizes --- are compared to the match. --- --- E.g. "rrdw" matches for either two dword registers or two word --- registers. "Fx2dq" matches an st0 operand plus an index operand --- pointing to a dword (float) or qword (double). --- --- Every character after the ":" is part of the pattern string: --- Hex chars are accumulated to form the opcode (left to right). --- "n" disables the standard opcode mods --- (otherwise: -1 for "b", o16 prefix for "w", rex.w for "q") --- "X" Force REX.W. --- "r"/"R" adds the reg. number from the 1st/2nd operand to the opcode. --- "m"/"M" generates ModRM/SIB from the 1st/2nd operand. --- The spare 3 bits are either filled with the last hex digit or --- the result from a previous "r"/"R". The opcode is restored. --- --- All of the following characters force a flush of the opcode: --- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand. --- "S" stores a signed 8 bit immediate from the last operand. --- "U" stores an unsigned 8 bit immediate from the last operand. --- "W" stores an unsigned 16 bit immediate from the last operand. --- "i" stores an operand sized immediate from the last operand. --- "I" dito, but generates an action code to optionally modify --- the opcode (+2) for a signed 8 bit immediate. --- "J" generates one of the REL action codes from the last operand. --- ------------------------------------------------------------------------------- - --- Template strings for x86 instructions. Ordered by first opcode byte. --- Unimplemented opcodes (deliberate omissions) are marked with *. -local map_op = { - -- 00-05: add... - -- 06: *push es - -- 07: *pop es - -- 08-0D: or... - -- 0E: *push cs - -- 0F: two byte opcode prefix - -- 10-15: adc... - -- 16: *push ss - -- 17: *pop ss - -- 18-1D: sbb... - -- 1E: *push ds - -- 1F: *pop ds - -- 20-25: and... - es_0 = "26", - -- 27: *daa - -- 28-2D: sub... - cs_0 = "2E", - -- 2F: *das - -- 30-35: xor... - ss_0 = "36", - -- 37: *aaa - -- 38-3D: cmp... - ds_0 = "3E", - -- 3F: *aas - inc_1 = x64 and "m:FF0m" or "rdw:40r|m:FF0m", - dec_1 = x64 and "m:FF1m" or "rdw:48r|m:FF1m", - push_1 = (x64 and "rq:n50r|rw:50r|mq:nFF6m|mw:FF6m" or - "rdw:50r|mdw:FF6m").."|S.:6AS|ib:n6Ai|i.:68i", - pop_1 = x64 and "rq:n58r|rw:58r|mq:n8F0m|mw:8F0m" or "rdw:58r|mdw:8F0m", - -- 60: *pusha, *pushad, *pushaw - -- 61: *popa, *popad, *popaw - -- 62: *bound rdw,x - -- 63: x86: *arpl mw,rw - movsxd_2 = x64 and "rm/qd:63rM", - fs_0 = "64", - gs_0 = "65", - o16_0 = "66", - a16_0 = not x64 and "67" or nil, - a32_0 = x64 and "67", - -- 68: push idw - -- 69: imul rdw,mdw,idw - -- 6A: push ib - -- 6B: imul rdw,mdw,S - -- 6C: *insb - -- 6D: *insd, *insw - -- 6E: *outsb - -- 6F: *outsd, *outsw - -- 70-7F: jcc lb - -- 80: add... mb,i - -- 81: add... mdw,i - -- 82: *undefined - -- 83: add... mdw,S - test_2 = "mr:85Rm|rm:85rM|Ri:A9ri|mi:F70mi", - -- 86: xchg rb,mb - -- 87: xchg rdw,mdw - -- 88: mov mb,r - -- 89: mov mdw,r - -- 8A: mov r,mb - -- 8B: mov r,mdw - -- 8C: *mov mdw,seg - lea_2 = "rx1dq:8DrM", - -- 8E: *mov seg,mdw - -- 8F: pop mdw - nop_0 = "90", - xchg_2 = "Rrqdw:90R|rRqdw:90r|rm:87rM|mr:87Rm", - cbw_0 = "6698", - cwde_0 = "98", - cdqe_0 = "4898", - cwd_0 = "6699", - cdq_0 = "99", - cqo_0 = "4899", - -- 9A: *call iw:idw - wait_0 = "9B", - fwait_0 = "9B", - pushf_0 = "9C", - pushfd_0 = not x64 and "9C", - pushfq_0 = x64 and "9C", - popf_0 = "9D", - popfd_0 = not x64 and "9D", - popfq_0 = x64 and "9D", - sahf_0 = "9E", - lahf_0 = "9F", - mov_2 = "OR:A3o|RO:A1O|mr:89Rm|rm:8BrM|rib:nB0ri|ridw:B8ri|mi:C70mi", - movsb_0 = "A4", - movsw_0 = "66A5", - movsd_0 = "A5", - cmpsb_0 = "A6", - cmpsw_0 = "66A7", - cmpsd_0 = "A7", - -- A8: test Rb,i - -- A9: test Rdw,i - stosb_0 = "AA", - stosw_0 = "66AB", - stosd_0 = "AB", - lodsb_0 = "AC", - lodsw_0 = "66AD", - lodsd_0 = "AD", - scasb_0 = "AE", - scasw_0 = "66AF", - scasd_0 = "AF", - -- B0-B7: mov rb,i - -- B8-BF: mov rdw,i - -- C0: rol... mb,i - -- C1: rol... mdw,i - ret_1 = "i.:nC2W", - ret_0 = "C3", - -- C4: *les rdw,mq - -- C5: *lds rdw,mq - -- C6: mov mb,i - -- C7: mov mdw,i - -- C8: *enter iw,ib - leave_0 = "C9", - -- CA: *retf iw - -- CB: *retf - int3_0 = "CC", - int_1 = "i.:nCDU", - into_0 = "CE", - -- CF: *iret - -- D0: rol... mb,1 - -- D1: rol... mdw,1 - -- D2: rol... mb,cl - -- D3: rol... mb,cl - -- D4: *aam ib - -- D5: *aad ib - -- D6: *salc - -- D7: *xlat - -- D8-DF: floating point ops - -- E0: *loopne - -- E1: *loope - -- E2: *loop - -- E3: *jcxz, *jecxz - -- E4: *in Rb,ib - -- E5: *in Rdw,ib - -- E6: *out ib,Rb - -- E7: *out ib,Rdw - call_1 = x64 and "mq:nFF2m|J.:E8nJ" or "md:FF2m|J.:E8J", - jmp_1 = x64 and "mq:nFF4m|J.:E9nJ" or "md:FF4m|J.:E9J", -- short: EB - -- EA: *jmp iw:idw - -- EB: jmp ib - -- EC: *in Rb,dx - -- ED: *in Rdw,dx - -- EE: *out dx,Rb - -- EF: *out dx,Rdw - lock_0 = "F0", - int1_0 = "F1", - repne_0 = "F2", - repnz_0 = "F2", - rep_0 = "F3", - repe_0 = "F3", - repz_0 = "F3", - -- F4: *hlt - cmc_0 = "F5", - -- F6: test... mb,i; div... mb - -- F7: test... mdw,i; div... mdw - clc_0 = "F8", - stc_0 = "F9", - -- FA: *cli - cld_0 = "FC", - std_0 = "FD", - -- FE: inc... mb - -- FF: inc... mdw - - -- misc ops - not_1 = "m:F72m", - neg_1 = "m:F73m", - mul_1 = "m:F74m", - imul_1 = "m:F75m", - div_1 = "m:F76m", - idiv_1 = "m:F77m", - - imul_2 = "rmqdw:0FAFrM|rIqdw:69rmI|rSqdw:6BrmS|riqdw:69rmi", - imul_3 = "rmIqdw:69rMI|rmSqdw:6BrMS|rmiqdw:69rMi", - - movzx_2 = "rm/db:0FB6rM|rm/qb:|rm/wb:0FB6rM|rm/dw:0FB7rM|rm/qw:", - movsx_2 = "rm/db:0FBErM|rm/qb:|rm/wb:0FBErM|rm/dw:0FBFrM|rm/qw:", - - bswap_1 = "rqd:0FC8r", - bsf_2 = "rmqdw:0FBCrM", - bsr_2 = "rmqdw:0FBDrM", - bt_2 = "mrqdw:0FA3Rm|miqdw:0FBA4mU", - btc_2 = "mrqdw:0FBBRm|miqdw:0FBA7mU", - btr_2 = "mrqdw:0FB3Rm|miqdw:0FBA6mU", - bts_2 = "mrqdw:0FABRm|miqdw:0FBA5mU", - - shld_3 = "mriqdw:0FA4RmU|mrCqdw:0FA5Rm", - shrd_3 = "mriqdw:0FACRmU|mrCqdw:0FADRm", - - rdtsc_0 = "0F31", -- P1+ - cpuid_0 = "0FA2", -- P1+ - - -- floating point ops - fst_1 = "ff:DDD0r|xd:D92m|xq:nDD2m", - fstp_1 = "ff:DDD8r|xd:D93m|xq:nDD3m|xt:DB7m", - fld_1 = "ff:D9C0r|xd:D90m|xq:nDD0m|xt:DB5m", - - fpop_0 = "DDD8", -- Alias for fstp st0. - - fist_1 = "xw:nDF2m|xd:DB2m", - fistp_1 = "xw:nDF3m|xd:DB3m|xq:nDF7m", - fild_1 = "xw:nDF0m|xd:DB0m|xq:nDF5m", - - fxch_0 = "D9C9", - fxch_1 = "ff:D9C8r", - fxch_2 = "fFf:D9C8r|Fff:D9C8R", - - fucom_1 = "ff:DDE0r", - fucom_2 = "Fff:DDE0R", - fucomp_1 = "ff:DDE8r", - fucomp_2 = "Fff:DDE8R", - fucomi_1 = "ff:DBE8r", -- P6+ - fucomi_2 = "Fff:DBE8R", -- P6+ - fucomip_1 = "ff:DFE8r", -- P6+ - fucomip_2 = "Fff:DFE8R", -- P6+ - fcomi_1 = "ff:DBF0r", -- P6+ - fcomi_2 = "Fff:DBF0R", -- P6+ - fcomip_1 = "ff:DFF0r", -- P6+ - fcomip_2 = "Fff:DFF0R", -- P6+ - fucompp_0 = "DAE9", - fcompp_0 = "DED9", - - fldenv_1 = "x.:D94m", - fnstenv_1 = "x.:D96m", - fstenv_1 = "x.:9BD96m", - fldcw_1 = "xw:nD95m", - fstcw_1 = "xw:n9BD97m", - fnstcw_1 = "xw:nD97m", - fstsw_1 = "Rw:n9BDFE0|xw:n9BDD7m", - fnstsw_1 = "Rw:nDFE0|xw:nDD7m", - fclex_0 = "9BDBE2", - fnclex_0 = "DBE2", - - fnop_0 = "D9D0", - -- D9D1-D9DF: unassigned - - fchs_0 = "D9E0", - fabs_0 = "D9E1", - -- D9E2: unassigned - -- D9E3: unassigned - ftst_0 = "D9E4", - fxam_0 = "D9E5", - -- D9E6: unassigned - -- D9E7: unassigned - fld1_0 = "D9E8", - fldl2t_0 = "D9E9", - fldl2e_0 = "D9EA", - fldpi_0 = "D9EB", - fldlg2_0 = "D9EC", - fldln2_0 = "D9ED", - fldz_0 = "D9EE", - -- D9EF: unassigned - - f2xm1_0 = "D9F0", - fyl2x_0 = "D9F1", - fptan_0 = "D9F2", - fpatan_0 = "D9F3", - fxtract_0 = "D9F4", - fprem1_0 = "D9F5", - fdecstp_0 = "D9F6", - fincstp_0 = "D9F7", - fprem_0 = "D9F8", - fyl2xp1_0 = "D9F9", - fsqrt_0 = "D9FA", - fsincos_0 = "D9FB", - frndint_0 = "D9FC", - fscale_0 = "D9FD", - fsin_0 = "D9FE", - fcos_0 = "D9FF", - - -- SSE, SSE2 - andnpd_2 = "rmo:660F55rM", - andnps_2 = "rmo:0F55rM", - andpd_2 = "rmo:660F54rM", - andps_2 = "rmo:0F54rM", - clflush_1 = "x.:0FAE7m", - cmppd_3 = "rmio:660FC2rMU", - cmpps_3 = "rmio:0FC2rMU", - cmpsd_3 = "rrio:F20FC2rMU|rxi/oq:", - cmpss_3 = "rrio:F30FC2rMU|rxi/od:", - comisd_2 = "rro:660F2FrM|rx/oq:", - comiss_2 = "rro:0F2FrM|rx/od:", - cvtdq2pd_2 = "rro:F30FE6rM|rx/oq:", - cvtdq2ps_2 = "rmo:0F5BrM", - cvtpd2dq_2 = "rmo:F20FE6rM", - cvtpd2ps_2 = "rmo:660F5ArM", - cvtpi2pd_2 = "rx/oq:660F2ArM", - cvtpi2ps_2 = "rx/oq:0F2ArM", - cvtps2dq_2 = "rmo:660F5BrM", - cvtps2pd_2 = "rro:0F5ArM|rx/oq:", - cvtsd2si_2 = "rr/do:F20F2DrM|rr/qo:|rx/dq:|rxq:", - cvtsd2ss_2 = "rro:F20F5ArM|rx/oq:", - cvtsi2sd_2 = "rm/od:F20F2ArM|rm/oq:F20F2ArXM", - cvtsi2ss_2 = "rm/od:F30F2ArM|rm/oq:F30F2ArXM", - cvtss2sd_2 = "rro:F30F5ArM|rx/od:", - cvtss2si_2 = "rr/do:F20F2CrM|rr/qo:|rxd:|rx/qd:", - cvttpd2dq_2 = "rmo:660FE6rM", - cvttps2dq_2 = "rmo:F30F5BrM", - cvttsd2si_2 = "rr/do:F20F2CrM|rr/qo:|rx/dq:|rxq:", - cvttss2si_2 = "rr/do:F30F2CrM|rr/qo:|rxd:|rx/qd:", - fxsave_1 = "x.:0FAE0m", - fxrstor_1 = "x.:0FAE1m", - ldmxcsr_1 = "xd:0FAE2m", - lfence_0 = "0FAEE8", - maskmovdqu_2 = "rro:660FF7rM", - mfence_0 = "0FAEF0", - movapd_2 = "rmo:660F28rM|mro:660F29Rm", - movaps_2 = "rmo:0F28rM|mro:0F29Rm", - movd_2 = "rm/od:660F6ErM|rm/oq:660F6ErXM|mr/do:660F7ERm|mr/qo:", - movdqa_2 = "rmo:660F6FrM|mro:660F7FRm", - movdqu_2 = "rmo:F30F6FrM|mro:F30F7FRm", - movhlps_2 = "rro:0F12rM", - movhpd_2 = "rx/oq:660F16rM|xr/qo:n660F17Rm", - movhps_2 = "rx/oq:0F16rM|xr/qo:n0F17Rm", - movlhps_2 = "rro:0F16rM", - movlpd_2 = "rx/oq:660F12rM|xr/qo:n660F13Rm", - movlps_2 = "rx/oq:0F12rM|xr/qo:n0F13Rm", - movmskpd_2 = "rr/do:660F50rM", - movmskps_2 = "rr/do:0F50rM", - movntdq_2 = "xro:660FE7Rm", - movnti_2 = "xrqd:0FC3Rm", - movntpd_2 = "xro:660F2BRm", - movntps_2 = "xro:0F2BRm", - movq_2 = "rro:F30F7ErM|rx/oq:|xr/qo:n660FD6Rm", - movsd_2 = "rro:F20F10rM|rx/oq:|xr/qo:nF20F11Rm", - movss_2 = "rro:F30F10rM|rx/od:|xr/do:F30F11Rm", - movupd_2 = "rmo:660F10rM|mro:660F11Rm", - movups_2 = "rmo:0F10rM|mro:0F11Rm", - orpd_2 = "rmo:660F56rM", - orps_2 = "rmo:0F56rM", - packssdw_2 = "rmo:660F6BrM", - packsswb_2 = "rmo:660F63rM", - packuswb_2 = "rmo:660F67rM", - paddb_2 = "rmo:660FFCrM", - paddd_2 = "rmo:660FFErM", - paddq_2 = "rmo:660FD4rM", - paddsb_2 = "rmo:660FECrM", - paddsw_2 = "rmo:660FEDrM", - paddusb_2 = "rmo:660FDCrM", - paddusw_2 = "rmo:660FDDrM", - paddw_2 = "rmo:660FFDrM", - pand_2 = "rmo:660FDBrM", - pandn_2 = "rmo:660FDFrM", - pause_0 = "F390", - pavgb_2 = "rmo:660FE0rM", - pavgw_2 = "rmo:660FE3rM", - pcmpeqb_2 = "rmo:660F74rM", - pcmpeqd_2 = "rmo:660F76rM", - pcmpeqw_2 = "rmo:660F75rM", - pcmpgtb_2 = "rmo:660F64rM", - pcmpgtd_2 = "rmo:660F66rM", - pcmpgtw_2 = "rmo:660F65rM", - pextrw_3 = "rri/do:660FC5rMU|xri/wo:660F3A15nrMU", -- Mem op: SSE4.1 only. - pinsrw_3 = "rri/od:660FC4rMU|rxi/ow:", - pmaddwd_2 = "rmo:660FF5rM", - pmaxsw_2 = "rmo:660FEErM", - pmaxub_2 = "rmo:660FDErM", - pminsw_2 = "rmo:660FEArM", - pminub_2 = "rmo:660FDArM", - pmovmskb_2 = "rr/do:660FD7rM", - pmulhuw_2 = "rmo:660FE4rM", - pmulhw_2 = "rmo:660FE5rM", - pmullw_2 = "rmo:660FD5rM", - pmuludq_2 = "rmo:660FF4rM", - por_2 = "rmo:660FEBrM", - prefetchnta_1 = "xb:n0F180m", - prefetcht0_1 = "xb:n0F181m", - prefetcht1_1 = "xb:n0F182m", - prefetcht2_1 = "xb:n0F183m", - psadbw_2 = "rmo:660FF6rM", - pshufd_3 = "rmio:660F70rMU", - pshufhw_3 = "rmio:F30F70rMU", - pshuflw_3 = "rmio:F20F70rMU", - pslld_2 = "rmo:660FF2rM|rio:660F726mU", - pslldq_2 = "rio:660F737mU", - psllq_2 = "rmo:660FF3rM|rio:660F736mU", - psllw_2 = "rmo:660FF1rM|rio:660F716mU", - psrad_2 = "rmo:660FE2rM|rio:660F724mU", - psraw_2 = "rmo:660FE1rM|rio:660F714mU", - psrld_2 = "rmo:660FD2rM|rio:660F722mU", - psrldq_2 = "rio:660F733mU", - psrlq_2 = "rmo:660FD3rM|rio:660F732mU", - psrlw_2 = "rmo:660FD1rM|rio:660F712mU", - psubb_2 = "rmo:660FF8rM", - psubd_2 = "rmo:660FFArM", - psubq_2 = "rmo:660FFBrM", - psubsb_2 = "rmo:660FE8rM", - psubsw_2 = "rmo:660FE9rM", - psubusb_2 = "rmo:660FD8rM", - psubusw_2 = "rmo:660FD9rM", - psubw_2 = "rmo:660FF9rM", - punpckhbw_2 = "rmo:660F68rM", - punpckhdq_2 = "rmo:660F6ArM", - punpckhqdq_2 = "rmo:660F6DrM", - punpckhwd_2 = "rmo:660F69rM", - punpcklbw_2 = "rmo:660F60rM", - punpckldq_2 = "rmo:660F62rM", - punpcklqdq_2 = "rmo:660F6CrM", - punpcklwd_2 = "rmo:660F61rM", - pxor_2 = "rmo:660FEFrM", - rcpps_2 = "rmo:0F53rM", - rcpss_2 = "rro:F30F53rM|rx/od:", - rsqrtps_2 = "rmo:0F52rM", - rsqrtss_2 = "rmo:F30F52rM", - sfence_0 = "0FAEF8", - shufpd_3 = "rmio:660FC6rMU", - shufps_3 = "rmio:0FC6rMU", - stmxcsr_1 = "xd:0FAE3m", - ucomisd_2 = "rro:660F2ErM|rx/oq:", - ucomiss_2 = "rro:0F2ErM|rx/od:", - unpckhpd_2 = "rmo:660F15rM", - unpckhps_2 = "rmo:0F15rM", - unpcklpd_2 = "rmo:660F14rM", - unpcklps_2 = "rmo:0F14rM", - xorpd_2 = "rmo:660F57rM", - xorps_2 = "rmo:0F57rM", - - -- SSE3 ops - fisttp_1 = "xw:nDF1m|xd:DB1m|xq:nDD1m", - addsubpd_2 = "rmo:660FD0rM", - addsubps_2 = "rmo:F20FD0rM", - haddpd_2 = "rmo:660F7CrM", - haddps_2 = "rmo:F20F7CrM", - hsubpd_2 = "rmo:660F7DrM", - hsubps_2 = "rmo:F20F7DrM", - lddqu_2 = "rxo:F20FF0rM", - movddup_2 = "rmo:F20F12rM", - movshdup_2 = "rmo:F30F16rM", - movsldup_2 = "rmo:F30F12rM", - - -- SSSE3 ops - pabsb_2 = "rmo:660F381CrM", - pabsd_2 = "rmo:660F381ErM", - pabsw_2 = "rmo:660F381DrM", - palignr_3 = "rmio:660F3A0FrMU", - phaddd_2 = "rmo:660F3802rM", - phaddsw_2 = "rmo:660F3803rM", - phaddw_2 = "rmo:660F3801rM", - phsubd_2 = "rmo:660F3806rM", - phsubsw_2 = "rmo:660F3807rM", - phsubw_2 = "rmo:660F3805rM", - pmaddubsw_2 = "rmo:660F3804rM", - pmulhrsw_2 = "rmo:660F380BrM", - pshufb_2 = "rmo:660F3800rM", - psignb_2 = "rmo:660F3808rM", - psignd_2 = "rmo:660F380ArM", - psignw_2 = "rmo:660F3809rM", - - -- SSE4.1 ops - blendpd_3 = "rmio:660F3A0DrMU", - blendps_3 = "rmio:660F3A0CrMU", - blendvpd_3 = "rmRo:660F3815rM", - blendvps_3 = "rmRo:660F3814rM", - dppd_3 = "rmio:660F3A41rMU", - dpps_3 = "rmio:660F3A40rMU", - extractps_3 = "mri/do:660F3A17RmU|rri/qo:660F3A17RXmU", - insertps_3 = "rrio:660F3A41rMU|rxi/od:", - movntdqa_2 = "rmo:660F382ArM", - mpsadbw_3 = "rmio:660F3A42rMU", - packusdw_2 = "rmo:660F382BrM", - pblendvb_3 = "rmRo:660F3810rM", - pblendw_3 = "rmio:660F3A0ErMU", - pcmpeqq_2 = "rmo:660F3829rM", - pextrb_3 = "rri/do:660F3A14nRmU|rri/qo:|xri/bo:", - pextrd_3 = "mri/do:660F3A16RmU", - pextrq_3 = "mri/qo:660F3A16RmU", - -- pextrw is SSE2, mem operand is SSE4.1 only - phminposuw_2 = "rmo:660F3841rM", - pinsrb_3 = "rri/od:660F3A20nrMU|rxi/ob:", - pinsrd_3 = "rmi/od:660F3A22rMU", - pinsrq_3 = "rmi/oq:660F3A22rXMU", - pmaxsb_2 = "rmo:660F383CrM", - pmaxsd_2 = "rmo:660F383DrM", - pmaxud_2 = "rmo:660F383FrM", - pmaxuw_2 = "rmo:660F383ErM", - pminsb_2 = "rmo:660F3838rM", - pminsd_2 = "rmo:660F3839rM", - pminud_2 = "rmo:660F383BrM", - pminuw_2 = "rmo:660F383ArM", - pmovsxbd_2 = "rro:660F3821rM|rx/od:", - pmovsxbq_2 = "rro:660F3822rM|rx/ow:", - pmovsxbw_2 = "rro:660F3820rM|rx/oq:", - pmovsxdq_2 = "rro:660F3825rM|rx/oq:", - pmovsxwd_2 = "rro:660F3823rM|rx/oq:", - pmovsxwq_2 = "rro:660F3824rM|rx/od:", - pmovzxbd_2 = "rro:660F3831rM|rx/od:", - pmovzxbq_2 = "rro:660F3832rM|rx/ow:", - pmovzxbw_2 = "rro:660F3830rM|rx/oq:", - pmovzxdq_2 = "rro:660F3835rM|rx/oq:", - pmovzxwd_2 = "rro:660F3833rM|rx/oq:", - pmovzxwq_2 = "rro:660F3834rM|rx/od:", - pmuldq_2 = "rmo:660F3828rM", - pmulld_2 = "rmo:660F3840rM", - ptest_2 = "rmo:660F3817rM", - roundpd_3 = "rmio:660F3A09rMU", - roundps_3 = "rmio:660F3A08rMU", - roundsd_3 = "rrio:660F3A0BrMU|rxi/oq:", - roundss_3 = "rrio:660F3A0ArMU|rxi/od:", - - -- SSE4.2 ops - crc32_2 = "rmqd:F20F38F1rM|rm/dw:66F20F38F1rM|rm/db:F20F38F0rM|rm/qb:", - pcmpestri_3 = "rmio:660F3A61rMU", - pcmpestrm_3 = "rmio:660F3A60rMU", - pcmpgtq_2 = "rmo:660F3837rM", - pcmpistri_3 = "rmio:660F3A63rMU", - pcmpistrm_3 = "rmio:660F3A62rMU", - popcnt_2 = "rmqdw:F30FB8rM", - - -- SSE4a - extrq_2 = "rro:660F79rM", - extrq_3 = "riio:660F780mUU", - insertq_2 = "rro:F20F79rM", - insertq_4 = "rriio:F20F78rMUU", - lzcnt_2 = "rmqdw:F30FBDrM", - movntsd_2 = "xr/qo:nF20F2BRm", - movntss_2 = "xr/do:F30F2BRm", - -- popcnt is also in SSE4.2 -} - ------------------------------------------------------------------------------- - --- Arithmetic ops. -for name,n in pairs{ add = 0, ["or"] = 1, adc = 2, sbb = 3, - ["and"] = 4, sub = 5, xor = 6, cmp = 7 } do - local n8 = shl(n, 3) - map_op[name.."_2"] = format( - "mr:%02XRm|rm:%02XrM|mI1qdw:81%XmI|mS1qdw:83%XmS|Ri1qdwb:%02Xri|mi1qdwb:81%Xmi", - 1+n8, 3+n8, n, n, 5+n8, n) -end - --- Shift ops. -for name,n in pairs{ rol = 0, ror = 1, rcl = 2, rcr = 3, - shl = 4, shr = 5, sar = 7, sal = 4 } do - map_op[name.."_2"] = format("m1:D1%Xm|mC1qdwb:D3%Xm|mi:C1%XmU", n, n, n) -end - --- Conditional ops. -for cc,n in pairs(map_cc) do - map_op["j"..cc.."_1"] = format("J.:n0F8%XJ", n) -- short: 7%X - map_op["set"..cc.."_1"] = format("mb:n0F9%X2m", n) - map_op["cmov"..cc.."_2"] = format("rmqdw:0F4%XrM", n) -- P6+ -end - --- FP arithmetic ops. -for name,n in pairs{ add = 0, mul = 1, com = 2, comp = 3, - sub = 4, subr = 5, div = 6, divr = 7 } do - local nc = 0xc0 + shl(n, 3) - local nr = nc + (n < 4 and 0 or (n % 2 == 0 and 8 or -8)) - local fn = "f"..name - map_op[fn.."_1"] = format("ff:D8%02Xr|xd:D8%Xm|xq:nDC%Xm", nc, n, n) - if n == 2 or n == 3 then - map_op[fn.."_2"] = format("Fff:D8%02XR|Fx2d:D8%XM|Fx2q:nDC%XM", nc, n, n) - else - map_op[fn.."_2"] = format("Fff:D8%02XR|fFf:DC%02Xr|Fx2d:D8%XM|Fx2q:nDC%XM", nc, nr, n, n) - map_op[fn.."p_1"] = format("ff:DE%02Xr", nr) - map_op[fn.."p_2"] = format("fFf:DE%02Xr", nr) - end - map_op["fi"..name.."_1"] = format("xd:DA%Xm|xw:nDE%Xm", n, n) -end - --- FP conditional moves. -for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do - local nc = 0xdac0 + shl(band(n, 3), 3) + shl(band(n, 4), 6) - map_op["fcmov"..cc.."_1"] = format("ff:%04Xr", nc) -- P6+ - map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+ -end - --- SSE FP arithmetic ops. -for name,n in pairs{ sqrt = 1, add = 8, mul = 9, - sub = 12, min = 13, div = 14, max = 15 } do - map_op[name.."ps_2"] = format("rmo:0F5%XrM", n) - map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n) - map_op[name.."pd_2"] = format("rmo:660F5%XrM", n) - map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n) -end - ------------------------------------------------------------------------------- - --- Process pattern string. -local function dopattern(pat, args, sz, op, needrex) - local digit, addin - local opcode = 0 - local szov = sz - local narg = 1 - local rex = 0 - - -- Limit number of section buffer positions used by a single dasm_put(). - -- A single opcode needs a maximum of 5 positions. - if secpos+5 > maxsecpos then wflush() end - - -- Process each character. - for c in gmatch(pat.."|", ".") do - if match(c, "%x") then -- Hex digit. - digit = byte(c) - 48 - if digit > 48 then digit = digit - 39 - elseif digit > 16 then digit = digit - 7 end - opcode = opcode*16 + digit - addin = nil - elseif c == "n" then -- Disable operand size mods for opcode. - szov = nil - elseif c == "X" then -- Force REX.W. - rex = 8 - elseif c == "r" then -- Merge 1st operand regno. into opcode. - addin = args[1]; opcode = opcode + (addin.reg % 8) - if narg < 2 then narg = 2 end - elseif c == "R" then -- Merge 2nd operand regno. into opcode. - addin = args[2]; opcode = opcode + (addin.reg % 8) - narg = 3 - elseif c == "m" or c == "M" then -- Encode ModRM/SIB. - local s - if addin then - s = addin.reg - opcode = opcode - band(s, 7) -- Undo regno opcode merge. - else - s = band(opcode, 15) -- Undo last digit. - opcode = shr(opcode, 4) - end - local nn = c == "m" and 1 or 2 - local t = args[nn] - if narg <= nn then narg = nn + 1 end - if szov == "q" and rex == 0 then rex = rex + 8 end - if t.reg and t.reg > 7 then rex = rex + 1 end - if t.xreg and t.xreg > 7 then rex = rex + 2 end - if s > 7 then rex = rex + 4 end - if needrex then rex = rex + 16 end - wputop(szov, opcode, rex); opcode = nil - local imark = sub(pat, -1) -- Force a mark (ugly). - -- Put ModRM/SIB with regno/last digit as spare. - wputmrmsib(t, imark, s, addin and addin.vreg) - addin = nil - else - if opcode then -- Flush opcode. - if szov == "q" and rex == 0 then rex = rex + 8 end - if needrex then rex = rex + 16 end - if addin and addin.reg == -1 then - wputop(szov, opcode - 7, rex) - waction("VREG", addin.vreg); wputxb(0) - else - if addin and addin.reg > 7 then rex = rex + 1 end - wputop(szov, opcode, rex) - end - opcode = nil - end - if c == "|" then break end - if c == "o" then -- Offset (pure 32 bit displacement). - wputdarg(args[1].disp); if narg < 2 then narg = 2 end - elseif c == "O" then - wputdarg(args[2].disp); narg = 3 - else - -- Anything else is an immediate operand. - local a = args[narg] - narg = narg + 1 - local mode, imm = a.mode, a.imm - if mode == "iJ" and not match("iIJ", c) then - werror("bad operand size for label") - end - if c == "S" then - wputsbarg(imm) - elseif c == "U" then - wputbarg(imm) - elseif c == "W" then - wputwarg(imm) - elseif c == "i" or c == "I" then - if mode == "iJ" then - wputlabel("IMM_", imm, 1) - elseif mode == "iI" and c == "I" then - waction(sz == "w" and "IMM_WB" or "IMM_DB", imm) - else - wputszarg(sz, imm) - end - elseif c == "J" then - if mode == "iPJ" then - waction("REL_A", imm) -- !x64 (secpos) - else - wputlabel("REL_", imm, 2) - end - else - werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'") - end - end - end - end -end - ------------------------------------------------------------------------------- - --- Mapping of operand modes to short names. Suppress output with '#'. -local map_modename = { - r = "reg", R = "eax", C = "cl", x = "mem", m = "mrm", i = "imm", - f = "stx", F = "st0", J = "lbl", ["1"] = "1", - I = "#", S = "#", O = "#", -} - --- Return a table/string showing all possible operand modes. -local function templatehelp(template, nparams) - if nparams == 0 then return "" end - local t = {} - for tm in gmatch(template, "[^%|]+") do - local s = map_modename[sub(tm, 1, 1)] - s = s..gsub(sub(tm, 2, nparams), ".", function(c) - return ", "..map_modename[c] - end) - if not match(s, "#") then t[#t+1] = s end - end - return t -end - --- Match operand modes against mode match part of template. -local function matchtm(tm, args) - for i=1,#args do - if not match(args[i].mode, sub(tm, i, i)) then return end - end - return true -end - --- Handle opcodes defined with template strings. -map_op[".template__"] = function(params, template, nparams) - if not params then return templatehelp(template, nparams) end - local args = {} - - -- Zero-operand opcodes have no match part. - if #params == 0 then - dopattern(template, args, "d", params.op, nil) - return - end - - -- Determine common operand size (coerce undefined size) or flag as mixed. - local sz, szmix, needrex - for i,p in ipairs(params) do - args[i] = parseoperand(p) - local nsz = args[i].opsize - if nsz then - if sz and sz ~= nsz then szmix = true else sz = nsz end - end - local nrex = args[i].needrex - if nrex ~= nil then - if needrex == nil then - needrex = nrex - elseif needrex ~= nrex then - werror("bad mix of byte-addressable registers") - end - end - end - - -- Try all match:pattern pairs (separated by '|'). - local gotmatch, lastpat - for tm in gmatch(template, "[^%|]+") do - -- Split off size match (starts after mode match) and pattern string. - local szm, pat = match(tm, "^(.-):(.*)$", #args+1) - if pat == "" then pat = lastpat else lastpat = pat end - if matchtm(tm, args) then - local prefix = sub(szm, 1, 1) - if prefix == "/" then -- Match both operand sizes. - if args[1].opsize == sub(szm, 2, 2) and - args[2].opsize == sub(szm, 3, 3) then - dopattern(pat, args, sz, params.op, needrex) -- Process pattern. - return - end - else -- Match common operand size. - local szp = sz - if szm == "" then szm = x64 and "qdwb" or "dwb" end -- Default sizes. - if prefix == "1" then szp = args[1].opsize; szmix = nil - elseif prefix == "2" then szp = args[2].opsize; szmix = nil end - if not szmix and (prefix == "." or match(szm, szp or "#")) then - dopattern(pat, args, szp, params.op, needrex) -- Process pattern. - return - end - end - gotmatch = true - end - end - - local msg = "bad operand mode" - if gotmatch then - if szmix then - msg = "mixed operand size" - else - msg = sz and "bad operand size" or "missing operand size" - end - end - - werror(msg.." in `"..opmodestr(params.op, args).."'") -end - ------------------------------------------------------------------------------- - --- x64-specific opcode for 64 bit immediates and displacements. -if x64 then - function map_op.mov64_2(params) - if not params then return { "reg, imm", "reg, [disp]", "[disp], reg" } end - if secpos+2 > maxsecpos then wflush() end - local opcode, op64, sz, rex, vreg - local op64 = match(params[1], "^%[%s*(.-)%s*%]$") - if op64 then - local a = parseoperand(params[2]) - if a.mode ~= "rmR" then werror("bad operand mode") end - sz = a.opsize - rex = sz == "q" and 8 or 0 - opcode = 0xa3 - else - op64 = match(params[2], "^%[%s*(.-)%s*%]$") - local a = parseoperand(params[1]) - if op64 then - if a.mode ~= "rmR" then werror("bad operand mode") end - sz = a.opsize - rex = sz == "q" and 8 or 0 - opcode = 0xa1 - else - if sub(a.mode, 1, 1) ~= "r" or a.opsize ~= "q" then - werror("bad operand mode") - end - op64 = params[2] - if a.reg == -1 then - vreg = a.vreg - opcode = 0xb8 - else - opcode = 0xb8 + band(a.reg, 7) - end - rex = a.reg > 7 and 9 or 8 - end - end - wputop(sz, opcode, rex) - if vreg then waction("VREG", vreg); wputxb(0) end - waction("IMM_D", format("(unsigned int)(%s)", op64)) - waction("IMM_D", format("(unsigned int)((%s)>>32)", op64)) - end -end - ------------------------------------------------------------------------------- - --- Pseudo-opcodes for data storage. -local function op_data(params) - if not params then return "imm..." end - local sz = sub(params.op, 2, 2) - if sz == "a" then sz = addrsize end - for _,p in ipairs(params) do - local a = parseoperand(p) - if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then - werror("bad mode or size in `"..p.."'") - end - if a.mode == "iJ" then - wputlabel("IMM_", a.imm, 1) - else - wputszarg(sz, a.imm) - end - if secpos+2 > maxsecpos then wflush() end - end -end - -map_op[".byte_*"] = op_data -map_op[".sbyte_*"] = op_data -map_op[".word_*"] = op_data -map_op[".dword_*"] = op_data -map_op[".aword_*"] = op_data - ------------------------------------------------------------------------------- - --- Pseudo-opcode to mark the position where the action list is to be emitted. -map_op[".actionlist_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeactions(out, name) end) -end - --- Pseudo-opcode to mark the position where the global enum is to be emitted. -map_op[".globals_1"] = function(params) - if not params then return "prefix" end - local prefix = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobals(out, prefix) end) -end - --- Pseudo-opcode to mark the position where the global names are to be emitted. -map_op[".globalnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeglobalnames(out, name) end) -end - --- Pseudo-opcode to mark the position where the extern names are to be emitted. -map_op[".externnames_1"] = function(params) - if not params then return "cvar" end - local name = params[1] -- No syntax check. You get to keep the pieces. - wline(function(out) writeexternnames(out, name) end) -end - ------------------------------------------------------------------------------- - --- Label pseudo-opcode (converted from trailing colon form). -map_op[".label_2"] = function(params) - if not params then return "[1-9] | ->global | =>pcexpr [, addr]" end - if secpos+2 > maxsecpos then wflush() end - local a = parseoperand(params[1]) - local mode, imm = a.mode, a.imm - if type(imm) == "number" and (mode == "iJ" or (imm >= 1 and imm <= 9)) then - -- Local label (1: ... 9:) or global label (->global:). - waction("LABEL_LG", nil, 1) - wputxb(imm) - elseif mode == "iJ" then - -- PC label (=>pcexpr:). - waction("LABEL_PC", imm) - else - werror("bad label definition") - end - -- SETLABEL must immediately follow LABEL_LG/LABEL_PC. - local addr = params[2] - if addr then - local a = parseoperand(addr) - if a.mode == "iPJ" then - waction("SETLABEL", a.imm) - else - werror("bad label assignment") - end - end -end -map_op[".label_1"] = map_op[".label_2"] - ------------------------------------------------------------------------------- - --- Alignment pseudo-opcode. -map_op[".align_1"] = function(params) - if not params then return "numpow2" end - if secpos+1 > maxsecpos then wflush() end - local align = tonumber(params[1]) or map_opsizenum[map_opsize[params[1]]] - if align then - local x = align - -- Must be a power of 2 in the range (2 ... 256). - for i=1,8 do - x = x / 2 - if x == 1 then - waction("ALIGN", nil, 1) - wputxb(align-1) -- Action byte is 2**n-1. - return - end - end - end - werror("bad alignment") -end - --- Spacing pseudo-opcode. -map_op[".space_2"] = function(params) - if not params then return "num [, filler]" end - if secpos+1 > maxsecpos then wflush() end - waction("SPACE", params[1]) - local fill = params[2] - if fill then - fill = tonumber(fill) - if not fill or fill < 0 or fill > 255 then werror("bad filler") end - end - wputxb(fill or 0) -end -map_op[".space_1"] = map_op[".space_2"] - ------------------------------------------------------------------------------- - --- Pseudo-opcode for (primitive) type definitions (map to C types). -map_op[".type_3"] = function(params, nparams) - if not params then - return nparams == 2 and "name, ctype" or "name, ctype, reg" - end - local name, ctype, reg = params[1], params[2], params[3] - if not match(name, "^[%a_][%w_]*$") then - werror("bad type name `"..name.."'") - end - local tp = map_type[name] - if tp then - werror("duplicate type `"..name.."'") - end - if reg and not map_reg_valid_base[reg] then - werror("bad base register `"..(map_reg_rev[reg] or reg).."'") - end - -- Add #type to defines. A bit unclean to put it in map_archdef. - map_archdef["#"..name] = "sizeof("..ctype..")" - -- Add new type and emit shortcut define. - local num = ctypenum + 1 - map_type[name] = { - ctype = ctype, - ctypefmt = format("Dt%X(%%s)", num), - reg = reg, - } - wline(format("#define Dt%X(_V) (int)(ptrdiff_t)&(((%s *)0)_V)", num, ctype)) - ctypenum = num -end -map_op[".type_2"] = map_op[".type_3"] - --- Dump type definitions. -local function dumptypes(out, lvl) - local t = {} - for name in pairs(map_type) do t[#t+1] = name end - sort(t) - out:write("Type definitions:\n") - for _,name in ipairs(t) do - local tp = map_type[name] - local reg = tp.reg and map_reg_rev[tp.reg] or "" - out:write(format(" %-20s %-20s %s\n", name, tp.ctype, reg)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Set the current section. -function _M.section(num) - waction("SECTION") - wputxb(num) - wflush(true) -- SECTION is a terminal action. -end - ------------------------------------------------------------------------------- - --- Dump architecture description. -function _M.dumparch(out) - out:write(format("DynASM %s version %s, released %s\n\n", - _info.arch, _info.version, _info.release)) - dumpregs(out) - dumpactions(out) -end - --- Dump all user defined elements. -function _M.dumpdef(out, lvl) - dumptypes(out, lvl) - dumpglobals(out, lvl) - dumpexterns(out, lvl) -end - ------------------------------------------------------------------------------- - --- Pass callbacks from/to the DynASM core. -function _M.passcb(wl, we, wf, ww) - wline, werror, wfatal, wwarn = wl, we, wf, ww - return wflush -end - --- Setup the arch-specific module. -function _M.setup(arch, opt) - g_arch, g_opt = arch, opt -end - --- Merge the core maps and the arch-specific maps. -function _M.mergemaps(map_coreop, map_def) - setmetatable(map_op, { __index = map_coreop }) - setmetatable(map_def, { __index = map_archdef }) - return map_op, map_def -end - -return _M - ------------------------------------------------------------------------------- - diff --git a/core/src/luajit/dynasm/dynasm.lua b/core/src/luajit/dynasm/dynasm.lua deleted file mode 100644 index fffda7513..000000000 --- a/core/src/luajit/dynasm/dynasm.lua +++ /dev/null @@ -1,1094 +0,0 @@ ------------------------------------------------------------------------------- --- DynASM. A dynamic assembler for code generation engines. --- Originally designed and implemented for LuaJIT. --- --- Copyright (C) 2005-2015 Mike Pall. All rights reserved. --- See below for full copyright notice. ------------------------------------------------------------------------------- - --- Application information. -local _info = { - name = "DynASM", - description = "A dynamic assembler for code generation engines", - version = "1.3.0", - vernum = 10300, - release = "2011-05-05", - author = "Mike Pall", - url = "http://luajit.org/dynasm.html", - license = "MIT", - copyright = [[ -Copyright (C) 2005-2015 Mike Pall. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -[ MIT license: http://www.opensource.org/licenses/mit-license.php ] -]], -} - --- Cache library functions. -local type, pairs, ipairs = type, pairs, ipairs -local pcall, error, assert = pcall, error, assert -local _s = string -local sub, match, gmatch, gsub = _s.sub, _s.match, _s.gmatch, _s.gsub -local format, rep, upper = _s.format, _s.rep, _s.upper -local _t = table -local insert, remove, concat, sort = _t.insert, _t.remove, _t.concat, _t.sort -local exit = os.exit -local io = io -local stdin, stdout, stderr = io.stdin, io.stdout, io.stderr - ------------------------------------------------------------------------------- - --- Program options. -local g_opt = {} - --- Global state for current file. -local g_fname, g_curline, g_indent, g_lineno, g_synclineno, g_arch -local g_errcount = 0 - --- Write buffer for output file. -local g_wbuffer, g_capbuffer - ------------------------------------------------------------------------------- - --- Write an output line (or callback function) to the buffer. -local function wline(line, needindent) - local buf = g_capbuffer or g_wbuffer - buf[#buf+1] = needindent and g_indent..line or line - g_synclineno = g_synclineno + 1 -end - --- Write assembler line as a comment, if requestd. -local function wcomment(aline) - if g_opt.comment then - wline(g_opt.comment..aline..g_opt.endcomment, true) - end -end - --- Resync CPP line numbers. -local function wsync() - if g_synclineno ~= g_lineno and g_opt.cpp then - wline("#line "..g_lineno..' "'..g_fname..'"') - g_synclineno = g_lineno - end -end - --- Dummy action flush function. Replaced with arch-specific function later. -local function wflush(term) -end - --- Dump all buffered output lines. -local function wdumplines(out, buf) - for _,line in ipairs(buf) do - if type(line) == "string" then - assert(out:write(line, "\n")) - else - -- Special callback to dynamically insert lines after end of processing. - line(out) - end - end -end - ------------------------------------------------------------------------------- - --- Emit an error. Processing continues with next statement. -local function werror(msg) - error(format("%s:%s: error: %s:\n%s", g_fname, g_lineno, msg, g_curline), 0) -end - --- Emit a fatal error. Processing stops. -local function wfatal(msg) - g_errcount = "fatal" - werror(msg) -end - --- Print a warning. Processing continues. -local function wwarn(msg) - stderr:write(format("%s:%s: warning: %s:\n%s\n", - g_fname, g_lineno, msg, g_curline)) -end - --- Print caught error message. But suppress excessive errors. -local function wprinterr(...) - if type(g_errcount) == "number" then - -- Regular error. - g_errcount = g_errcount + 1 - if g_errcount < 21 then -- Seems to be a reasonable limit. - stderr:write(...) - elseif g_errcount == 21 then - stderr:write(g_fname, - ":*: warning: too many errors (suppressed further messages).\n") - end - else - -- Fatal error. - stderr:write(...) - return true -- Stop processing. - end -end - ------------------------------------------------------------------------------- - --- Map holding all option handlers. -local opt_map = {} -local opt_current - --- Print error and exit with error status. -local function opterror(...) - stderr:write("dynasm.lua: ERROR: ", ...) - stderr:write("\n") - exit(1) -end - --- Get option parameter. -local function optparam(args) - local argn = args.argn - local p = args[argn] - if not p then - opterror("missing parameter for option `", opt_current, "'.") - end - args.argn = argn + 1 - return p -end - ------------------------------------------------------------------------------- - --- Core pseudo-opcodes. -local map_coreop = {} --- Dummy opcode map. Replaced by arch-specific map. -local map_op = {} - --- Forward declarations. -local dostmt -local readfile - ------------------------------------------------------------------------------- - --- Map for defines (initially empty, chains to arch-specific map). -local map_def = {} - --- Pseudo-opcode to define a substitution. -map_coreop[".define_2"] = function(params, nparams) - if not params then return nparams == 1 and "name" or "name, subst" end - local name, def = params[1], params[2] or "1" - if not match(name, "^[%a_][%w_]*$") then werror("bad or duplicate define") end - map_def[name] = def -end -map_coreop[".define_1"] = map_coreop[".define_2"] - --- Define a substitution on the command line. -function opt_map.D(args) - local namesubst = optparam(args) - local name, subst = match(namesubst, "^([%a_][%w_]*)=(.*)$") - if name then - map_def[name] = subst - elseif match(namesubst, "^[%a_][%w_]*$") then - map_def[namesubst] = "1" - else - opterror("bad define") - end -end - --- Undefine a substitution on the command line. -function opt_map.U(args) - local name = optparam(args) - if match(name, "^[%a_][%w_]*$") then - map_def[name] = nil - else - opterror("bad define") - end -end - --- Helper for definesubst. -local gotsubst - -local function definesubst_one(word) - local subst = map_def[word] - if subst then gotsubst = word; return subst else return word end -end - --- Iteratively substitute defines. -local function definesubst(stmt) - -- Limit number of iterations. - for i=1,100 do - gotsubst = false - stmt = gsub(stmt, "#?[%w_]+", definesubst_one) - if not gotsubst then break end - end - if gotsubst then wfatal("recursive define involving `"..gotsubst.."'") end - return stmt -end - --- Dump all defines. -local function dumpdefines(out, lvl) - local t = {} - for name in pairs(map_def) do - t[#t+1] = name - end - sort(t) - out:write("Defines:\n") - for _,name in ipairs(t) do - local subst = map_def[name] - if g_arch then subst = g_arch.revdef(subst) end - out:write(format(" %-20s %s\n", name, subst)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Support variables for conditional assembly. -local condlevel = 0 -local condstack = {} - --- Evaluate condition with a Lua expression. Substitutions already performed. -local function cond_eval(cond) - local func, err - if setfenv then - func, err = loadstring("return "..cond, "=expr") - else - -- No globals. All unknown identifiers evaluate to nil. - func, err = load("return "..cond, "=expr", "t", {}) - end - if func then - if setfenv then - setfenv(func, {}) -- No globals. All unknown identifiers evaluate to nil. - end - local ok, res = pcall(func) - if ok then - if res == 0 then return false end -- Oh well. - return not not res - end - err = res - end - wfatal("bad condition: "..err) -end - --- Skip statements until next conditional pseudo-opcode at the same level. -local function stmtskip() - local dostmt_save = dostmt - local lvl = 0 - dostmt = function(stmt) - local op = match(stmt, "^%s*(%S+)") - if op == ".if" then - lvl = lvl + 1 - elseif lvl ~= 0 then - if op == ".endif" then lvl = lvl - 1 end - elseif op == ".elif" or op == ".else" or op == ".endif" then - dostmt = dostmt_save - dostmt(stmt) - end - end -end - --- Pseudo-opcodes for conditional assembly. -map_coreop[".if_1"] = function(params) - if not params then return "condition" end - local lvl = condlevel + 1 - local res = cond_eval(params[1]) - condlevel = lvl - condstack[lvl] = res - if not res then stmtskip() end -end - -map_coreop[".elif_1"] = function(params) - if not params then return "condition" end - if condlevel == 0 then wfatal(".elif without .if") end - local lvl = condlevel - local res = condstack[lvl] - if res then - if res == "else" then wfatal(".elif after .else") end - else - res = cond_eval(params[1]) - if res then - condstack[lvl] = res - return - end - end - stmtskip() -end - -map_coreop[".else_0"] = function(params) - if condlevel == 0 then wfatal(".else without .if") end - local lvl = condlevel - local res = condstack[lvl] - condstack[lvl] = "else" - if res then - if res == "else" then wfatal(".else after .else") end - stmtskip() - end -end - -map_coreop[".endif_0"] = function(params) - local lvl = condlevel - if lvl == 0 then wfatal(".endif without .if") end - condlevel = lvl - 1 -end - --- Check for unfinished conditionals. -local function checkconds() - if g_errcount ~= "fatal" and condlevel ~= 0 then - wprinterr(g_fname, ":*: error: unbalanced conditional\n") - end -end - ------------------------------------------------------------------------------- - --- Search for a file in the given path and open it for reading. -local function pathopen(path, name) - local dirsep = package and match(package.path, "\\") and "\\" or "/" - for _,p in ipairs(path) do - local fullname = p == "" and name or p..dirsep..name - local fin = io.open(fullname, "r") - if fin then - g_fname = fullname - return fin - end - end -end - --- Include a file. -map_coreop[".include_1"] = function(params) - if not params then return "filename" end - local name = params[1] - -- Save state. Ugly, I know. but upvalues are fast. - local gf, gl, gcl, gi = g_fname, g_lineno, g_curline, g_indent - -- Read the included file. - local fatal = readfile(pathopen(g_opt.include, name) or - wfatal("include file `"..name.."' not found")) - -- Restore state. - g_synclineno = -1 - g_fname, g_lineno, g_curline, g_indent = gf, gl, gcl, gi - if fatal then wfatal("in include file") end -end - --- Make .include and conditionals initially available, too. -map_op[".include_1"] = map_coreop[".include_1"] -map_op[".if_1"] = map_coreop[".if_1"] -map_op[".elif_1"] = map_coreop[".elif_1"] -map_op[".else_0"] = map_coreop[".else_0"] -map_op[".endif_0"] = map_coreop[".endif_0"] - ------------------------------------------------------------------------------- - --- Support variables for macros. -local mac_capture, mac_lineno, mac_name -local mac_active = {} -local mac_list = {} - --- Pseudo-opcode to define a macro. -map_coreop[".macro_*"] = function(mparams) - if not mparams then return "name [, params...]" end - -- Split off and validate macro name. - local name = remove(mparams, 1) - if not name then werror("missing macro name") end - if not (match(name, "^[%a_][%w_%.]*$") or match(name, "^%.[%w_%.]*$")) then - wfatal("bad macro name `"..name.."'") - end - -- Validate macro parameter names. - local mdup = {} - for _,mp in ipairs(mparams) do - if not match(mp, "^[%a_][%w_]*$") then - wfatal("bad macro parameter name `"..mp.."'") - end - if mdup[mp] then wfatal("duplicate macro parameter name `"..mp.."'") end - mdup[mp] = true - end - -- Check for duplicate or recursive macro definitions. - local opname = name.."_"..#mparams - if map_op[opname] or map_op[name.."_*"] then - wfatal("duplicate macro `"..name.."' ("..#mparams.." parameters)") - end - if mac_capture then wfatal("recursive macro definition") end - - -- Enable statement capture. - local lines = {} - mac_lineno = g_lineno - mac_name = name - mac_capture = function(stmt) -- Statement capture function. - -- Stop macro definition with .endmacro pseudo-opcode. - if not match(stmt, "^%s*.endmacro%s*$") then - lines[#lines+1] = stmt - return - end - mac_capture = nil - mac_lineno = nil - mac_name = nil - mac_list[#mac_list+1] = opname - -- Add macro-op definition. - map_op[opname] = function(params) - if not params then return mparams, lines end - -- Protect against recursive macro invocation. - if mac_active[opname] then wfatal("recursive macro invocation") end - mac_active[opname] = true - -- Setup substitution map. - local subst = {} - for i,mp in ipairs(mparams) do subst[mp] = params[i] end - local mcom - if g_opt.maccomment and g_opt.comment then - mcom = " MACRO "..name.." ("..#mparams..")" - wcomment("{"..mcom) - end - -- Loop through all captured statements - for _,stmt in ipairs(lines) do - -- Substitute macro parameters. - local st = gsub(stmt, "[%w_]+", subst) - st = definesubst(st) - st = gsub(st, "%s*%.%.%s*", "") -- Token paste a..b. - if mcom and sub(st, 1, 1) ~= "|" then wcomment(st) end - -- Emit statement. Use a protected call for better diagnostics. - local ok, err = pcall(dostmt, st) - if not ok then - -- Add the captured statement to the error. - wprinterr(err, "\n", g_indent, "| ", stmt, - "\t[MACRO ", name, " (", #mparams, ")]\n") - end - end - if mcom then wcomment("}"..mcom) end - mac_active[opname] = nil - end - end -end - --- An .endmacro pseudo-opcode outside of a macro definition is an error. -map_coreop[".endmacro_0"] = function(params) - wfatal(".endmacro without .macro") -end - --- Dump all macros and their contents (with -PP only). -local function dumpmacros(out, lvl) - sort(mac_list) - out:write("Macros:\n") - for _,opname in ipairs(mac_list) do - local name = sub(opname, 1, -3) - local params, lines = map_op[opname]() - out:write(format(" %-20s %s\n", name, concat(params, ", "))) - if lvl > 1 then - for _,line in ipairs(lines) do - out:write(" |", line, "\n") - end - out:write("\n") - end - end - out:write("\n") -end - --- Check for unfinished macro definitions. -local function checkmacros() - if mac_capture then - wprinterr(g_fname, ":", mac_lineno, - ": error: unfinished .macro `", mac_name ,"'\n") - end -end - ------------------------------------------------------------------------------- - --- Support variables for captures. -local cap_lineno, cap_name -local cap_buffers = {} -local cap_used = {} - --- Start a capture. -map_coreop[".capture_1"] = function(params) - if not params then return "name" end - wflush() - local name = params[1] - if not match(name, "^[%a_][%w_]*$") then - wfatal("bad capture name `"..name.."'") - end - if cap_name then - wfatal("already capturing to `"..cap_name.."' since line "..cap_lineno) - end - cap_name = name - cap_lineno = g_lineno - -- Create or continue a capture buffer and start the output line capture. - local buf = cap_buffers[name] - if not buf then buf = {}; cap_buffers[name] = buf end - g_capbuffer = buf - g_synclineno = 0 -end - --- Stop a capture. -map_coreop[".endcapture_0"] = function(params) - wflush() - if not cap_name then wfatal(".endcapture without a valid .capture") end - cap_name = nil - cap_lineno = nil - g_capbuffer = nil - g_synclineno = 0 -end - --- Dump a capture buffer. -map_coreop[".dumpcapture_1"] = function(params) - if not params then return "name" end - wflush() - local name = params[1] - if not match(name, "^[%a_][%w_]*$") then - wfatal("bad capture name `"..name.."'") - end - cap_used[name] = true - wline(function(out) - local buf = cap_buffers[name] - if buf then wdumplines(out, buf) end - end) - g_synclineno = 0 -end - --- Dump all captures and their buffers (with -PP only). -local function dumpcaptures(out, lvl) - out:write("Captures:\n") - for name,buf in pairs(cap_buffers) do - out:write(format(" %-20s %4s)\n", name, "("..#buf)) - if lvl > 1 then - local bar = rep("=", 76) - out:write(" ", bar, "\n") - for _,line in ipairs(buf) do - out:write(" ", line, "\n") - end - out:write(" ", bar, "\n\n") - end - end - out:write("\n") -end - --- Check for unfinished or unused captures. -local function checkcaptures() - if cap_name then - wprinterr(g_fname, ":", cap_lineno, - ": error: unfinished .capture `", cap_name,"'\n") - return - end - for name in pairs(cap_buffers) do - if not cap_used[name] then - wprinterr(g_fname, ":*: error: missing .dumpcapture ", name ,"\n") - end - end -end - ------------------------------------------------------------------------------- - --- Sections names. -local map_sections = {} - --- Pseudo-opcode to define code sections. --- TODO: Data sections, BSS sections. Needs extra C code and API. -map_coreop[".section_*"] = function(params) - if not params then return "name..." end - if #map_sections > 0 then werror("duplicate section definition") end - wflush() - for sn,name in ipairs(params) do - local opname = "."..name.."_0" - if not match(name, "^[%a][%w_]*$") or - map_op[opname] or map_op["."..name.."_*"] then - werror("bad section name `"..name.."'") - end - map_sections[#map_sections+1] = name - wline(format("#define DASM_SECTION_%s\t%d", upper(name), sn-1)) - map_op[opname] = function(params) g_arch.section(sn-1) end - end - wline(format("#define DASM_MAXSECTION\t\t%d", #map_sections)) -end - --- Dump all sections. -local function dumpsections(out, lvl) - out:write("Sections:\n") - for _,name in ipairs(map_sections) do - out:write(format(" %s\n", name)) - end - out:write("\n") -end - ------------------------------------------------------------------------------- - --- Replacement for customized Lua, which lacks the package library. -local prefix = "" -if not require then - function require(name) - local fp = assert(io.open(prefix..name..".lua")) - local s = fp:read("*a") - assert(fp:close()) - return assert(loadstring(s, "@"..name..".lua"))() - end -end - --- Load architecture-specific module. -local function loadarch(arch) - if not match(arch, "^[%w_]+$") then return "bad arch name" end - local ok, m_arch = pcall(require, "dasm_"..arch) - if not ok then return "cannot load module: "..m_arch end - g_arch = m_arch - wflush = m_arch.passcb(wline, werror, wfatal, wwarn) - m_arch.setup(arch, g_opt) - map_op, map_def = m_arch.mergemaps(map_coreop, map_def) -end - --- Dump architecture description. -function opt_map.dumparch(args) - local name = optparam(args) - if not g_arch then - local err = loadarch(name) - if err then opterror(err) end - end - - local t = {} - for name in pairs(map_coreop) do t[#t+1] = name end - for name in pairs(map_op) do t[#t+1] = name end - sort(t) - - local out = stdout - local _arch = g_arch._info - out:write(format("%s version %s, released %s, %s\n", - _info.name, _info.version, _info.release, _info.url)) - g_arch.dumparch(out) - - local pseudo = true - out:write("Pseudo-Opcodes:\n") - for _,sname in ipairs(t) do - local name, nparam = match(sname, "^(.+)_([0-9%*])$") - if name then - if pseudo and sub(name, 1, 1) ~= "." then - out:write("\nOpcodes:\n") - pseudo = false - end - local f = map_op[sname] - local s - if nparam ~= "*" then nparam = nparam + 0 end - if nparam == 0 then - s = "" - elseif type(f) == "string" then - s = map_op[".template__"](nil, f, nparam) - else - s = f(nil, nparam) - end - if type(s) == "table" then - for _,s2 in ipairs(s) do - out:write(format(" %-12s %s\n", name, s2)) - end - else - out:write(format(" %-12s %s\n", name, s)) - end - end - end - out:write("\n") - exit(0) -end - --- Pseudo-opcode to set the architecture. --- Only initially available (map_op is replaced when called). -map_op[".arch_1"] = function(params) - if not params then return "name" end - local err = loadarch(params[1]) - if err then wfatal(err) end - wline(format("#if DASM_VERSION != %d", _info.vernum)) - wline('#error "Version mismatch between DynASM and included encoding engine"') - wline("#endif") -end - --- Dummy .arch pseudo-opcode to improve the error report. -map_coreop[".arch_1"] = function(params) - if not params then return "name" end - wfatal("duplicate .arch statement") -end - ------------------------------------------------------------------------------- - --- Dummy pseudo-opcode. Don't confuse '.nop' with 'nop'. -map_coreop[".nop_*"] = function(params) - if not params then return "[ignored...]" end -end - --- Pseudo-opcodes to raise errors. -map_coreop[".error_1"] = function(params) - if not params then return "message" end - werror(params[1]) -end - -map_coreop[".fatal_1"] = function(params) - if not params then return "message" end - wfatal(params[1]) -end - --- Dump all user defined elements. -local function dumpdef(out) - local lvl = g_opt.dumpdef - if lvl == 0 then return end - dumpsections(out, lvl) - dumpdefines(out, lvl) - if g_arch then g_arch.dumpdef(out, lvl) end - dumpmacros(out, lvl) - dumpcaptures(out, lvl) -end - ------------------------------------------------------------------------------- - --- Helper for splitstmt. -local splitlvl - -local function splitstmt_one(c) - if c == "(" then - splitlvl = ")"..splitlvl - elseif c == "[" then - splitlvl = "]"..splitlvl - elseif c == "{" then - splitlvl = "}"..splitlvl - elseif c == ")" or c == "]" or c == "}" then - if sub(splitlvl, 1, 1) ~= c then werror("unbalanced (), [] or {}") end - splitlvl = sub(splitlvl, 2) - elseif splitlvl == "" then - return " \0 " - end - return c -end - --- Split statement into (pseudo-)opcode and params. -local function splitstmt(stmt) - -- Convert label with trailing-colon into .label statement. - local label = match(stmt, "^%s*(.+):%s*$") - if label then return ".label", {label} end - - -- Split at commas and equal signs, but obey parentheses and brackets. - splitlvl = "" - stmt = gsub(stmt, "[,%(%)%[%]{}]", splitstmt_one) - if splitlvl ~= "" then werror("unbalanced () or []") end - - -- Split off opcode. - local op, other = match(stmt, "^%s*([^%s%z]+)%s*(.*)$") - if not op then werror("bad statement syntax") end - - -- Split parameters. - local params = {} - for p in gmatch(other, "%s*(%Z+)%z?") do - params[#params+1] = gsub(p, "%s+$", "") - end - if #params > 16 then werror("too many parameters") end - - params.op = op - return op, params -end - --- Process a single statement. -dostmt = function(stmt) - -- Ignore empty statements. - if match(stmt, "^%s*$") then return end - - -- Capture macro defs before substitution. - if mac_capture then return mac_capture(stmt) end - stmt = definesubst(stmt) - - -- Emit C code without parsing the line. - if sub(stmt, 1, 1) == "|" then - local tail = sub(stmt, 2) - wflush() - if sub(tail, 1, 2) == "//" then wcomment(tail) else wline(tail, true) end - return - end - - -- Split into (pseudo-)opcode and params. - local op, params = splitstmt(stmt) - - -- Get opcode handler (matching # of parameters or generic handler). - local f = map_op[op.."_"..#params] or map_op[op.."_*"] - if not f then - if not g_arch then wfatal("first statement must be .arch") end - -- Improve error report. - for i=0,9 do - if map_op[op.."_"..i] then - werror("wrong number of parameters for `"..op.."'") - end - end - werror("unknown statement `"..op.."'") - end - - -- Call opcode handler or special handler for template strings. - if type(f) == "string" then - map_op[".template__"](params, f) - else - f(params) - end -end - --- Process a single line. -local function doline(line) - if g_opt.flushline then wflush() end - - -- Assembler line? - local indent, aline = match(line, "^(%s*)%|(.*)$") - if not aline then - -- No, plain C code line, need to flush first. - wflush() - wsync() - wline(line, false) - return - end - - g_indent = indent -- Remember current line indentation. - - -- Emit C code (even from macros). Avoids echo and line parsing. - if sub(aline, 1, 1) == "|" then - if not mac_capture then - wsync() - elseif g_opt.comment then - wsync() - wcomment(aline) - end - dostmt(aline) - return - end - - -- Echo assembler line as a comment. - if g_opt.comment then - wsync() - wcomment(aline) - end - - -- Strip assembler comments. - aline = gsub(aline, "//.*$", "") - - -- Split line into statements at semicolons. - if match(aline, ";") then - for stmt in gmatch(aline, "[^;]+") do dostmt(stmt) end - else - dostmt(aline) - end -end - ------------------------------------------------------------------------------- - --- Write DynASM header. -local function dasmhead(out) - out:write(format([[ -/* -** This file has been pre-processed with DynASM. -** %s -** DynASM version %s, DynASM %s version %s -** DO NOT EDIT! The original file is in "%s". -*/ - -]], _info.url, - _info.version, g_arch._info.arch, g_arch._info.version, - g_fname)) -end - --- Read input file. -readfile = function(fin) - g_indent = "" - g_lineno = 0 - g_synclineno = -1 - - -- Process all lines. - for line in fin:lines() do - g_lineno = g_lineno + 1 - g_curline = line - local ok, err = pcall(doline, line) - if not ok and wprinterr(err, "\n") then return true end - end - wflush() - - -- Close input file. - assert(fin == stdin or fin:close()) -end - --- Write output file. -local function writefile(outfile) - local fout - - -- Open output file. - if outfile == nil or outfile == "-" then - fout = stdout - else - fout = assert(io.open(outfile, "w")) - end - - -- Write all buffered lines - wdumplines(fout, g_wbuffer) - - -- Close output file. - assert(fout == stdout or fout:close()) - - -- Optionally dump definitions. - dumpdef(fout == stdout and stderr or stdout) -end - --- Translate an input file to an output file. -local function translate(infile, outfile) - g_wbuffer = {} - g_indent = "" - g_lineno = 0 - g_synclineno = -1 - - -- Put header. - wline(dasmhead) - - -- Read input file. - local fin - if infile == "-" then - g_fname = "(stdin)" - fin = stdin - else - g_fname = infile - fin = assert(io.open(infile, "r")) - end - readfile(fin) - - -- Check for errors. - if not g_arch then - wprinterr(g_fname, ":*: error: missing .arch directive\n") - end - checkconds() - checkmacros() - checkcaptures() - - if g_errcount ~= 0 then - stderr:write(g_fname, ":*: info: ", g_errcount, " error", - (type(g_errcount) == "number" and g_errcount > 1) and "s" or "", - " in input file -- no output file generated.\n") - dumpdef(stderr) - exit(1) - end - - -- Write output file. - writefile(outfile) -end - ------------------------------------------------------------------------------- - --- Print help text. -function opt_map.help() - stdout:write("DynASM -- ", _info.description, ".\n") - stdout:write("DynASM ", _info.version, " ", _info.release, " ", _info.url, "\n") - stdout:write[[ - -Usage: dynasm [OPTION]... INFILE.dasc|- - - -h, --help Display this help text. - -V, --version Display version and copyright information. - - -o, --outfile FILE Output file name (default is stdout). - -I, --include DIR Add directory to the include search path. - - -c, --ccomment Use /* */ comments for assembler lines. - -C, --cppcomment Use // comments for assembler lines (default). - -N, --nocomment Suppress assembler lines in output. - -M, --maccomment Show macro expansions as comments (default off). - - -L, --nolineno Suppress CPP line number information in output. - -F, --flushline Flush action list for every line. - - -D NAME[=SUBST] Define a substitution. - -U NAME Undefine a substitution. - - -P, --dumpdef Dump defines, macros, etc. Repeat for more output. - -A, --dumparch ARCH Load architecture ARCH and dump description. -]] - exit(0) -end - --- Print version information. -function opt_map.version() - stdout:write(format("%s version %s, released %s\n%s\n\n%s", - _info.name, _info.version, _info.release, _info.url, _info.copyright)) - exit(0) -end - --- Misc. options. -function opt_map.outfile(args) g_opt.outfile = optparam(args) end -function opt_map.include(args) insert(g_opt.include, 1, optparam(args)) end -function opt_map.ccomment() g_opt.comment = "/*|"; g_opt.endcomment = " */" end -function opt_map.cppcomment() g_opt.comment = "//|"; g_opt.endcomment = "" end -function opt_map.nocomment() g_opt.comment = false end -function opt_map.maccomment() g_opt.maccomment = true end -function opt_map.nolineno() g_opt.cpp = false end -function opt_map.flushline() g_opt.flushline = true end -function opt_map.dumpdef() g_opt.dumpdef = g_opt.dumpdef + 1 end - ------------------------------------------------------------------------------- - --- Short aliases for long options. -local opt_alias = { - h = "help", ["?"] = "help", V = "version", - o = "outfile", I = "include", - c = "ccomment", C = "cppcomment", N = "nocomment", M = "maccomment", - L = "nolineno", F = "flushline", - P = "dumpdef", A = "dumparch", -} - --- Parse single option. -local function parseopt(opt, args) - opt_current = #opt == 1 and "-"..opt or "--"..opt - local f = opt_map[opt] or opt_map[opt_alias[opt]] - if not f then - opterror("unrecognized option `", opt_current, "'. Try `--help'.\n") - end - f(args) -end - --- Parse arguments. -local function parseargs(args) - -- Default options. - g_opt.comment = "//|" - g_opt.endcomment = "" - g_opt.cpp = true - g_opt.dumpdef = 0 - g_opt.include = { "" } - - -- Process all option arguments. - args.argn = 1 - repeat - local a = args[args.argn] - if not a then break end - local lopt, opt = match(a, "^%-(%-?)(.+)") - if not opt then break end - args.argn = args.argn + 1 - if lopt == "" then - -- Loop through short options. - for o in gmatch(opt, ".") do parseopt(o, args) end - else - -- Long option. - parseopt(opt, args) - end - until false - - -- Check for proper number of arguments. - local nargs = #args - args.argn + 1 - if nargs ~= 1 then - if nargs == 0 then - if g_opt.dumpdef > 0 then return dumpdef(stdout) end - end - opt_map.help() - end - - -- Translate a single input file to a single output file - -- TODO: Handle multiple files? - translate(args[args.argn], g_opt.outfile) -end - ------------------------------------------------------------------------------- - --- Add the directory dynasm.lua resides in to the Lua module search path. -local arg = arg -if arg and arg[0] then - prefix = match(arg[0], "^(.*[/\\])") - if package and prefix then package.path = prefix.."?.lua;"..package.path end -end - --- Start DynASM. -parseargs{...} - ------------------------------------------------------------------------------- - diff --git a/core/src/luajit/etc/luajit.1 b/core/src/luajit/etc/luajit.1 deleted file mode 100644 index fd38b0a92..000000000 --- a/core/src/luajit/etc/luajit.1 +++ /dev/null @@ -1,88 +0,0 @@ -.TH luajit 1 "" "" "LuaJIT documentation" -.SH NAME -luajit \- Just-In-Time Compiler for the Lua Language -\fB -.SH SYNOPSIS -.B luajit -[\fIoptions\fR]... [\fIscript\fR [\fIargs\fR]...] -.SH "WEB SITE" -.IR http://luajit.org -.SH DESCRIPTION -.PP -This is the command-line program to run Lua programs with \fBLuaJIT\fR. -.PP -\fBLuaJIT\fR is a just-in-time (JIT) compiler for the Lua language. -The virtual machine (VM) is based on a fast interpreter combined with -a trace compiler. It can significantly improve the performance of Lua programs. -.PP -\fBLuaJIT\fR is API\- and ABI-compatible with the VM of the standard -Lua\ 5.1 interpreter. When embedding the VM into an application, -the built library can be used as a drop-in replacement. -.SH OPTIONS -.TP -.BI "\-e " chunk -Run the given chunk of Lua code. -.TP -.BI "\-l " library -Load the named library, just like \fBrequire("\fR\fIlibrary\fR\fB")\fR. -.TP -.BI "\-b " ... -Save or list bytecode. Run without arguments to get help on options. -.TP -.BI "\-j " command -Perform LuaJIT control command (optional space after \fB\-j\fR). -.TP -.BI "\-O" [opt] -Control LuaJIT optimizations. -.TP -.B "\-i" -Run in interactive mode. -.TP -.B "\-v" -Show \fBLuaJIT\fR version. -.TP -.B "\-E" -Ignore environment variables. -.TP -.B "\-\-" -Stop processing options. -.TP -.B "\-" -Read script from stdin instead. -.PP -After all options are processed, the given \fIscript\fR is run. -The arguments are passed in the global \fIarg\fR table. -.PP -Interactive mode is only entered, if no \fIscript\fR and no \fB\-e\fR -option is given. Interactive mode can be left with EOF (\fICtrl\-Z\fB). -.SH EXAMPLES -.TP -luajit hello.lua world - -Prints "Hello world", assuming \fIhello.lua\fR contains: -.br - print("Hello", arg[1]) -.TP -luajit \-e "local x=0; for i=1,1e9 do x=x+i end; print(x)" - -Calculates the sum of the numbers from 1 to 1000000000. -.br -And finishes in a reasonable amount of time, too. -.TP -luajit \-jv \-e "for i=1,10 do for j=1,10 do for k=1,100 do end end end" - -Runs some nested loops and shows the resulting traces. -.SH COPYRIGHT -.PP -\fBLuaJIT\fR is Copyright \(co 2005-2015 Mike Pall. -.br -\fBLuaJIT\fR is open source software, released under the MIT license. -.SH SEE ALSO -.PP -More details in the provided HTML docs or at: -.IR http://luajit.org -.br -More about the Lua language can be found at: -.IR http://lua.org/docs.html -.PP -lua(1) diff --git a/core/src/luajit/etc/luajit.pc b/core/src/luajit/etc/luajit.pc deleted file mode 100644 index a652b40d4..000000000 --- a/core/src/luajit/etc/luajit.pc +++ /dev/null @@ -1,25 +0,0 @@ -# Package information for LuaJIT to be used by pkg-config. -majver=2 -minver=0 -relver=4 -version=${majver}.${minver}.${relver} -abiver=5.1 - -prefix=/usr/local -multilib=lib -exec_prefix=${prefix} -libdir=${exec_prefix}/${multilib} -libname=luajit-${abiver} -includedir=${prefix}/include/luajit-${majver}.${minver} - -INSTALL_LMOD=${prefix}/share/lua/${abiver} -INSTALL_CMOD=${prefix}/${multilib}/lua/${abiver} - -Name: LuaJIT -Description: Just-in-time compiler for Lua -URL: http://luajit.org -Version: ${version} -Requires: -Libs: -L${libdir} -l${libname} -Libs.private: -Wl,-E -lm -ldl -Cflags: -I${includedir} diff --git a/core/src/sv/test/CMakeLists.txt b/core/src/sv/test/CMakeLists.txt deleted file mode 100644 index 89d4a0eec..000000000 --- a/core/src/sv/test/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -add_executable(version version.c) -target_link_libraries(version ${PROJECT_NAME}) -add_test(version version) - -add_executable(comp comp.c) -target_link_libraries(comp ${PROJECT_NAME}) -add_test(comp comp) - -add_executable(range range.c) -target_link_libraries(range ${PROJECT_NAME}) -add_test(range range) - -add_executable(match match.c) -target_link_libraries(match ${PROJECT_NAME}) -add_test(match match) - -add_executable(utils utils.c) -target_link_libraries(utils ${PROJECT_NAME}) -add_test(utils utils) - -add_executable(usage usage.c) -target_link_libraries(usage ${PROJECT_NAME}) -add_test(usage usage) - -add_executable(semvers semvers.c) -target_link_libraries(semvers ${PROJECT_NAME}) -add_test(semvers semvers) diff --git a/core/src/sv/test/comp.c b/core/src/sv/test/comp.c deleted file mode 100644 index faa68a500..000000000 --- a/core/src/sv/test/comp.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * This is free and unencumbered software released into the public domain. - * - * Anyone is free to copy, modify, publish, use, compile, sell, or - * distribute this software, either in source code form or as a compiled - * binary, for any purpose, commercial or non-commercial, and by any - * means. - * - * In jurisdictions that recognize copyright laws, the author or authors - * of this software dedicate any and all copyright interest in the - * software to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and - * successors. We intend this dedication to be an overt act of - * relinquishment in perpetuity of all present and future rights to this - * software under copyright law. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * For more information, please refer to <http://unlicense.org> - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "semver.h" - -#define STRNSIZE(s) (s), sizeof(s)-1 - -int test_read(const char *expected, const char *str, size_t len) { - unsigned slen; - char buffer[1024]; - semver_comp_t comp = {0}; - - printf("test: `%.*s`", (int) len, str); - if (semver_compn(&comp, str, len)) { - puts(" \tcouldn't parse"); - return 1; - } - slen = (unsigned) semver_comp_write(comp, buffer, 1024); - printf(" \t=> \t`%.*s`", slen, buffer); - if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { - printf(" != `%s`\n", expected); - semver_comp_dtor(&comp); - return 1; - } - printf(" == `%s`\n", expected); - semver_comp_dtor(&comp); - return 0; -} - -int test_and(const char *expected, const char *base_str, size_t base_len, const char *str, size_t len) { - unsigned slen; - char buffer[1024]; - semver_comp_t comp = {0}; - - printf("test and: `%.*s`", (int) base_len, base_str); - if (semver_compn(&comp, base_str, base_len)) { - puts(" \tcouldn't parse"); - return 1; - } - if (semver_and(&comp, str, len)) { - puts(" \tand failed"); - return 1; - } - slen = (unsigned) semver_comp_write(comp, buffer, 1024); - printf(" \t=> \t`%.*s`", slen, buffer); - if (memcmp(expected, buffer, (size_t) slen > base_len + len + 1 ? slen : base_len + len + 1) != 0) { - printf(" != `%s`\n", expected); - semver_comp_dtor(&comp); - return 1; - } - printf(" == `%s`\n", expected); - semver_comp_dtor(&comp); - return 0; -} - -int main(void) { - puts("failure:"); - if (test_read("", STRNSIZE("* ")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("* ")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("* |")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("* || *")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("abc")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE(">")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("<=")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("~")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("^")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("=")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE(">a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("<a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("~a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("^a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("=a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE(">1.a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("<1.a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("~1.a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("^1.a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("=1.a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.3 ")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.3 -")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.3 - ")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.3 -a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.3 - a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.3 - 1.2.a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("a.2.3")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.a.3")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.3-")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.3-alpha+")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("1.2.3+")) == 0) { - return EXIT_FAILURE; - } - if (test_read("1.2.3", STRNSIZE("1.2.3"))) { - return EXIT_FAILURE; - } - - puts("\nsome prerelease and build:"); - if (test_read(">=0.0.0 1.2.3-alpha", STRNSIZE("* 1.2.3-alpha"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0 1.2.3-alpha.2", STRNSIZE("* 1.2.3-alpha.2"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0 1.2.3+77", STRNSIZE("* 1.2.3+77"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0 1.2.3+77.2", STRNSIZE("* 1.2.3+77.2"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0 1.2.3-alpha.2+77", STRNSIZE("* 1.2.3-alpha.2+77"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0 1.2.3-alpha.2+77.2", STRNSIZE("* 1.2.3-alpha.2+77.2"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0 1.2.3-al-pha.2+77", STRNSIZE("* 1.2.3-al-pha.2+77"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0 1.2.3-al-pha.2+77.2", STRNSIZE("* 1.2.3-al-pha.2+77.2"))) { - return EXIT_FAILURE; - } - - puts("\nx-range:"); - if (test_read(">=0.0.0", STRNSIZE("*"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.0.0 <2.0.0", STRNSIZE("1.x"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.0 <1.3.0", STRNSIZE("1.2.x"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0", STRNSIZE(""))) { - return EXIT_FAILURE; - } - if (test_read(">=1.0.0 <2.0.0", STRNSIZE("1"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.0 <1.3.0", STRNSIZE("1.2"))) { - return EXIT_FAILURE; - } - - puts("\nhyphen:"); - if (test_read(">=1.2.3 <=2.3.4", STRNSIZE("1.2.3 - 2.3.4"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.0 <=2.3.4", STRNSIZE("1.2 - 2.3.4"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.3 <2.4.0", STRNSIZE("1.2.3 - 2.3"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.3 <3.0.0", STRNSIZE("1.2.3 - 2"))) { - return EXIT_FAILURE; - } - - puts("\ntidle:"); - if (test_read(">=1.2.3 <1.3.0", STRNSIZE("~1.2.3"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.0 <1.3.0", STRNSIZE("~1.2"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.0.0 <2.0.0", STRNSIZE("~1"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.2.3 <0.3.0", STRNSIZE("~0.2.3"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.2.0 <0.3.0", STRNSIZE("~0.2"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0 <1.0.0", STRNSIZE("~0"))) { - return EXIT_FAILURE; - } - - puts("\ncaret:"); - if (test_read(">=1.2.3 <2.0.0", STRNSIZE("^1.2.3"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.2.3 <0.3.0", STRNSIZE("^0.2.3"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.3 <0.0.4", STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - - puts("\nprimitive:"); - if (test_read(">=1.2.3 <2.0.0", STRNSIZE(">=1.2.3 <2.0"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.2.3 <0.3.0", STRNSIZE(">=0.2.3 <0.3"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.5.0 <0.0.4", STRNSIZE(">=0.5 <0.0.4"))) { - return EXIT_FAILURE; - } - if (test_read(">0.0.3", STRNSIZE(">0.0.3"))) { - return EXIT_FAILURE; - } - if (test_read("0.0.3", STRNSIZE("=0.0.3"))) { - return EXIT_FAILURE; - } - if (test_read("9.0.0", STRNSIZE("=9"))) { - return EXIT_FAILURE; - } - - puts("\nand:"); - if (test_and(">=0.0.0 >=0.0.3 <0.0.4", STRNSIZE("*"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_and(">=1.0.0 <2.0.0 >=0.0.3 <0.0.4", STRNSIZE("1.x"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_and(">=1.2.0 <1.3.0 >=0.0.3 <0.0.4", STRNSIZE("1.2.x"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_and(">=1.2.0 <1.3.0 >=1.2.0 <1.3.0 >=0.0.3 <0.0.4", STRNSIZE("1.2 1.2.x"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_and(">=1.0.0 <2.0.0 >=0.0.3 <0.0.4", STRNSIZE("1"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_and(">=1.2.0 <1.3.0 >=0.0.3 <0.0.4", STRNSIZE("1.2"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_and("", STRNSIZE("1.2"), STRNSIZE("")) == 0) { - return EXIT_FAILURE; - } - if (test_and("", STRNSIZE("1.2"), STRNSIZE("a")) == 0) { - return EXIT_FAILURE; - } - if (test_and("", STRNSIZE("1.2"), STRNSIZE("1.2.x abc")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget " - "dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascet" - "ur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, s")) - == 0) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/core/src/sv/test/match.c b/core/src/sv/test/match.c deleted file mode 100644 index d960bb7fc..000000000 --- a/core/src/sv/test/match.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * This is free and unencumbered software released into the public domain. - * - * Anyone is free to copy, modify, publish, use, compile, sell, or - * distribute this software, either in source code form or as a compiled - * binary, for any purpose, commercial or non-commercial, and by any - * means. - * - * In jurisdictions that recognize copyright laws, the author or authors - * of this software dedicate any and all copyright interest in the - * software to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and - * successors. We intend this dedication to be an overt act of - * relinquishment in perpetuity of all present and future rights to this - * software under copyright law. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * For more information, please refer to <http://unlicense.org> - */ - -#include <stdlib.h> -#include <stdio.h> - -#include "semver.h" - -#define STRNSIZE(s) (s), sizeof(s)-1 - -int test_matchn(bool expected, const char *semver_str, size_t semver_len, const char *comp_str, size_t comp_len) { - bool result; - semver_t semver = {0}; - - printf("test: `%.*s` ^ `%.*s`", (int) semver_len, semver_str, (int) comp_len, comp_str); - if (semvern(&semver, semver_str, semver_len)) { - puts(" \tcouldn't parse semver"); - return 1; - } - result = semver_comp_matchn(&semver, comp_str, comp_len); - printf(" \t=> %d\t", result); - if (result != expected) { - printf(" != `%d`\n", expected); - semver_dtor(&semver); - return 1; - } - printf(" == `%d`\n", expected); - semver_dtor(&semver); - return 0; -} - -int test_rmatchn(bool expected, const char *semver_str, size_t semver_len, const char *range_str, size_t range_len) { - bool result; - semver_t semver = {0}; - - printf("test: `%.*s` ^ `%.*s`", (int) semver_len, semver_str, (int) range_len, range_str); - if (semvern(&semver, semver_str, semver_len)) { - puts(" \tcouldn't parse semver"); - return 1; - } - result = semver_range_matchn(&semver, range_str, range_len); - printf(" \t=> %d\t", result); - if (result != expected) { - printf(" != `%d`\n", expected); - semver_dtor(&semver); - return 1; - } - printf(" == `%d`\n", expected); - semver_dtor(&semver); - return 0; -} - -int main(void) { - if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1.2.3"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1.2.x"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1.x.x"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1.x"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("*"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE(">1"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE(">2"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE(">=2"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE("<1"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE("<=1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE(">=1.2.3"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE(">1.2.3"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE("<1.2.3"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("v1.2.3"), STRNSIZE("<=1.2.3"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("v1.2.3"), STRNSIZE("2.x"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("<0.0.1-99"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("<=0.0.1-99"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("<=0.0.1-98"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("=0.0.1-98"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE(">=0.0.1-98"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE(">=0.0.1-97"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE(">0.0.1-97"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha"), STRNSIZE("0.0.1-alpha"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("<0.0.1-99"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<0.0.1-alpha.99"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<=0.0.1-alpha.99"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<=0.0.1-alpha.98"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("=0.0.1-alpha.98"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">=0.0.1-alpha.98"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">=0.0.1-alpha.97"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">0.0.1-alpha.97"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<0.0.1-alpha.99.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<=0.0.1-alpha.99.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("<=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">=0.0.1-alpha.97.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE(">0.0.1-alpha.97.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("<0.0.1-alpha.99.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("<=0.0.1-alpha.99.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("<=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(false, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE(">=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE(">=0.0.1-alpha.97.1"))) { - return EXIT_FAILURE; - } - if (test_matchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE(">0.0.1-alpha.97.1"))) { - return EXIT_FAILURE; - } - - if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1.2.3"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1.2.x"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1.x.x"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1.x"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || *"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >2"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >=2"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || <1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || <=1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >=1.2.3"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || >1.2.3"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || <1.2.3"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("v1.2.3"), STRNSIZE("9.x || <=1.2.3"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("v1.2.3"), STRNSIZE("9.x || 2.x"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || <0.0.1-99"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || <=0.0.1-99"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || <=0.0.1-98"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || =0.0.1-98"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || >=0.0.1-98"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || >=0.0.1-97"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || >0.0.1-97"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha"), STRNSIZE("9.x || 0.0.1-alpha"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-98"), STRNSIZE("9.x || <0.0.1-99"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <0.0.1-alpha.99"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <=0.0.1-alpha.99"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <=0.0.1-alpha.98"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || =0.0.1-alpha.98"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >=0.0.1-alpha.98"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >=0.0.1-alpha.97"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >0.0.1-alpha.97"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <0.0.1-alpha.99.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <=0.0.1-alpha.99.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || <=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || =0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >=0.0.1-alpha.97.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98"), STRNSIZE("9.x || >0.0.1-alpha.97.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || <0.0.1-alpha.99.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || <=0.0.1-alpha.99.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || <=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(false, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || =0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || >=0.0.1-alpha.98.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || >=0.0.1-alpha.97.1"))) { - return EXIT_FAILURE; - } - if (test_rmatchn(true, STRNSIZE("0.0.1-alpha.98.1.3"), STRNSIZE("9.x || >0.0.1-alpha.97.1"))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/core/src/sv/test/range.c b/core/src/sv/test/range.c deleted file mode 100644 index 17611ab25..000000000 --- a/core/src/sv/test/range.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * This is free and unencumbered software released into the public domain. - * - * Anyone is free to copy, modify, publish, use, compile, sell, or - * distribute this software, either in source code form or as a compiled - * binary, for any purpose, commercial or non-commercial, and by any - * means. - * - * In jurisdictions that recognize copyright laws, the author or authors - * of this software dedicate any and all copyright interest in the - * software to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and - * successors. We intend this dedication to be an overt act of - * relinquishment in perpetuity of all present and future rights to this - * software under copyright law. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * For more information, please refer to <http://unlicense.org> - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "semver.h" - -#define STRNSIZE(s) (s), sizeof(s)-1 - -int test_read(const char *expected, const char *str, size_t len) { - unsigned slen; - char buffer[1024]; - semver_range_t range = {0}; - - printf("test: `%.*s`", (int) len, str); - if (semver_rangen(&range, str, len)) { - puts(" \tcouldn't parse"); - return 1; - } - slen = (unsigned) semver_range_write(range, buffer, 1024); - printf(" \t=> \t`%.*s`", slen, buffer); - if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { - printf(" != `%s`\n", expected); - semver_range_dtor(&range); - return 1; - } - printf(" == `%s`\n", expected); - semver_range_dtor(&range); - return 0; -} - -int test_or(const char *expected, const char *base_str, size_t base_len, const char *str, size_t len) { - unsigned slen; - char buffer[1024]; - semver_range_t range = {0}; - - printf("test and: `%.*s`", (int) base_len, base_str); - if (semver_rangen(&range, base_str, base_len)) { - puts(" \tcouldn't parse base"); - return 1; - } - if (semver_or(&range, str, len)) { - puts(" \tand failed"); - return 1; - } - slen = (unsigned) semver_range_write(range, buffer, 1024); - printf(" \t=> \t`%.*s`", slen, buffer); - if (memcmp(expected, buffer, (size_t) slen > base_len + len + 1 ? slen : base_len + len + 1) != 0) { - printf(" != `%s`\n", expected); - semver_range_dtor(&range); - return 1; - } - printf(" == `%s`\n", expected); - semver_range_dtor(&range); - return 0; -} - -int main(void) { - puts("failure:"); - if (test_read("", STRNSIZE("* |")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("* ||a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("* || a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("* || 1.a")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget " - "dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascet" - "ur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, s")) - == 0) { - return EXIT_FAILURE; - } - - puts("\nx-range:"); - if (test_read(">=0.0.0 || 1.2.3", STRNSIZE("* || 1.2.3"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.0.0 <2.0.0 || >=2.0.0 <3.0.0", STRNSIZE("1.x || 2.x"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.0 <1.3.0 || 3.0.0", STRNSIZE("1.2.x || 3.0.0"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0", STRNSIZE(""))) { - return EXIT_FAILURE; - } - if (test_read(">=1.0.0 <2.0.0 || >=2.0.0 <3.0.0 || >=3.0.0 <4.0.0", STRNSIZE("1 || 2 || 3"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.0 <1.3.0 || >=5.0.0", STRNSIZE("1.2 || >=5"))) { - return EXIT_FAILURE; - } - - puts("\nhyphen:"); - if (test_read(">=1.2.3 <=2.3.4 || >=5.0.0", STRNSIZE("1.2.3 - 2.3.4 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.0 <=2.3.4 || >=5.0.0", STRNSIZE("1.2 - 2.3.4 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.3 <2.4.0 || >=5.0.0", STRNSIZE("1.2.3 - 2.3 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.3 <3.0.0 || >=5.0.0", STRNSIZE("1.2.3 - 2 || >=5"))) { - return EXIT_FAILURE; - } - - puts("\ntidle:"); - if (test_read(">=1.2.3 <1.3.0 || >=5.0.0", STRNSIZE("~1.2.3 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.2.0 <1.3.0 || >=5.0.0", STRNSIZE("~1.2 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=1.0.0 <2.0.0 || >=5.0.0", STRNSIZE("~1 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.2.3 <0.3.0 || >=5.0.0", STRNSIZE("~0.2.3 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.2.0 <0.3.0 || >=5.0.0", STRNSIZE("~0.2 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.0 <1.0.0 || >=5.0.0", STRNSIZE("~0 || >=5"))) { - return EXIT_FAILURE; - } - - puts("\ncaret:"); - if (test_read(">=1.2.3 <2.0.0 || >=5.0.0", STRNSIZE("^1.2.3 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.2.3 <0.3.0 || >=5.0.0", STRNSIZE("^0.2.3 || >=5"))) { - return EXIT_FAILURE; - } - if (test_read(">=0.0.3 <0.0.4 || >=5.0.0", STRNSIZE("^0.0.3 || >=5"))) { - return EXIT_FAILURE; - } - - puts("\nand:"); - if (test_or(">=0.0.0 || >=0.0.3 <0.0.4", STRNSIZE("*"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_or(">=1.0.0 <2.0.0 || >=0.0.3 <0.0.4", STRNSIZE("1.x"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_or(">=1.2.0 <1.3.0 || >=0.0.3 <0.0.4", STRNSIZE("1.2.x"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_or(">=1.2.0 <1.3.0 || >=1.2.0 <1.3.0 || >=0.0.3 <0.0.4", STRNSIZE("1.2 || 1.2.x"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_or(">=1.0.0 <2.0.0 || >=0.0.3 <0.0.4", STRNSIZE("1"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_or(">=1.2.0 <1.3.0 || >=0.0.3 <0.0.4", STRNSIZE("1.2"), STRNSIZE("^0.0.3"))) { - return EXIT_FAILURE; - } - if (test_or("", STRNSIZE("1.2"), STRNSIZE("")) == 0) { - return EXIT_FAILURE; - } - if (test_or("", STRNSIZE("1.2"), STRNSIZE("a")) == 0) { - return EXIT_FAILURE; - } - if (test_or("", STRNSIZE("1.2"), STRNSIZE("1.2.x || abc")) == 0) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/core/src/sv/test/semver.c b/core/src/sv/test/semver.c deleted file mode 100644 index 762f4ce40..000000000 --- a/core/src/sv/test/semver.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This is free and unencumbered software released into the public domain. - * - * Anyone is free to copy, modify, publish, use, compile, sell, or - * distribute this software, either in source code form or as a compiled - * binary, for any purpose, commercial or non-commercial, and by any - * means. - * - * In jurisdictions that recognize copyright laws, the author or authors - * of this software dedicate any and all copyright interest in the - * software to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and - * successors. We intend this dedication to be an overt act of - * relinquishment in perpetuity of all present and future rights to this - * software under copyright law. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * For more information, please refer to <http://unlicense.org> - */ - -#include <semver.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#define STRNSIZE(s) (s), sizeof(s)-1 - -int test_semver(const char *expected, const char *str, size_t len) { - size_t offset = 0; - unsigned slen; - char buffer[1024]; - semver_t semver = {0}; - - printf("test: `%.*s`", (int) len, str); - if (semver_read(&semver, str, len, &offset)) { - puts(" \tcouldn't parse"); - return 1; - } - slen = (unsigned) semver_write(semver, buffer, 1024); - printf(" \t=> \t`%.*s`", slen, buffer); - if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { - printf(" != `%s`\n", expected); - semver_dtor(&semver); - return 1; - } - printf(" == `%s`\n", expected); - semver_dtor(&semver); - return 0; -} - -int main(void) { - if (test_semver("1.2.3", STRNSIZE("1.2.3"))) { - return EXIT_FAILURE; - } - if (test_semver("1.2.3-alpha", STRNSIZE("v1.2.3-alpha"))) { - return EXIT_FAILURE; - } - if (test_semver("1.2.3-alpha.2", STRNSIZE("1.2.3-alpha.2"))) { - return EXIT_FAILURE; - } - if (test_semver("1.2.3+77", STRNSIZE("v1.2.3+77"))) { - return EXIT_FAILURE; - } - if (test_semver("1.2.3+77.2", STRNSIZE("1.2.3+77.2"))) { - return EXIT_FAILURE; - } - if (test_semver("1.2.3-alpha.2+77", STRNSIZE("v1.2.3-alpha.2+77"))) { - return EXIT_FAILURE; - } - if (test_semver("1.2.3-alpha.2+77.2", STRNSIZE("1.2.3-alpha.2+77.2"))) { - return EXIT_FAILURE; - } - if (test_semver("1.2.3-al-pha.2+77", STRNSIZE("v1.2.3-al-pha.2+77"))) { - return EXIT_FAILURE; - } - if (test_semver("1.2.3-al-pha.2+77.2", STRNSIZE("1.2.3-al-pha.2+77.2"))) { - return EXIT_FAILURE; - } - if (test_semver("", STRNSIZE("")) == 0) { - return EXIT_FAILURE; - } - if (test_semver("", STRNSIZE("vv1.2.3")) == 0) { - return EXIT_FAILURE; - } - if (test_semver("", STRNSIZE("v1.2")) == 0) { - return EXIT_FAILURE; - } - if (test_semver("", STRNSIZE("v1.2.x")) == 0) { - return EXIT_FAILURE; - } - if (test_semver("", STRNSIZE("v1.2.3-")) == 0) { - return EXIT_FAILURE; - } - if (test_semver("", STRNSIZE("v1.2.3+")) == 0) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/core/src/sv/test/semvers.c b/core/src/sv/test/semvers.c deleted file mode 100644 index fec6072bd..000000000 --- a/core/src/sv/test/semvers.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This is free and unencumbered software released into the public domain. - * - * Anyone is free to copy, modify, publish, use, compile, sell, or - * distribute this software, either in source code form or as a compiled - * binary, for any purpose, commercial or non-commercial, and by any - * means. - * - * In jurisdictions that recognize copyright laws, the author or authors - * of this software dedicate any and all copyright interest in the - * software to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and - * successors. We intend this dedication to be an overt act of - * relinquishment in perpetuity of all present and future rights to this - * software under copyright law. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * For more information, please refer to <http://unlicense.org> - */ - -#include <stdlib.h> -#include <assert.h> - -#include "semver.h" - -#define STRNSIZE(s) (s), sizeof(s)-1 - -int main(void) { - semver_t v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10; - semvers_t semvers = {0}; - - semver_tryn(&v0, STRNSIZE("2.0.0")); - semver_tryn(&v1, STRNSIZE("2.0.1")); - semver_tryn(&v2, STRNSIZE("2.0.2")); - semver_tryn(&v3, STRNSIZE("v2.0.0")); - semver_tryn(&v4, STRNSIZE("v2.0.1")); - semver_tryn(&v5, STRNSIZE("v2.0.2")); - semver_tryn(&v6, STRNSIZE("v2.0.3")); - semver_tryn(&v7, STRNSIZE("v2.1.0-beta1")); - semver_tryn(&v8, STRNSIZE("v2.1.0-beta2")); - semver_tryn(&v9, STRNSIZE("v2.0")); - semver_tryn(&v10, STRNSIZE("v2.1")); - - if (semver_rmatch(v0, ">2.0.1")) semvers_push(semvers, v0); - if (semver_rmatch(v1, ">2.0.1")) semvers_unshift(semvers, v1); - if (semver_rmatch(v2, ">2.0.1")) semvers_push(semvers, v2); - if (semver_rmatch(v3, ">2.0.1")) semvers_unshift(semvers, v3); - if (semver_rmatch(v4, ">2.0.1")) semvers_push(semvers, v4); - if (semver_rmatch(v5, ">2.0.1")) semvers_unshift(semvers, v5); - if (semver_rmatch(v6, ">2.0.1")) semvers_push(semvers, v6); - if (semver_rmatch(v7, ">2.0.1")) semvers_unshift(semvers, v7); - if (semver_rmatch(v8, ">2.0.1")) semvers_push(semvers, v8); - if (semver_rmatch(v9, ">2.0.1")) semvers_unshift(semvers, v9); - if (semver_rmatch(v10, ">2.0.1")) semvers_push(semvers, v10); - if (semver_rmatch(v0, ">2.0.1")) semvers_push(semvers, v0); - if (semver_rmatch(v1, ">2.0.1")) semvers_unshift(semvers, v1); - if (semver_rmatch(v2, ">2.0.1")) semvers_push(semvers, v2); - if (semver_rmatch(v3, ">2.0.1")) semvers_unshift(semvers, v3); - if (semver_rmatch(v4, ">2.0.1")) semvers_push(semvers, v4); - if (semver_rmatch(v5, ">2.0.1")) semvers_unshift(semvers, v5); - if (semver_rmatch(v6, ">2.0.1")) semvers_push(semvers, v6); - if (semver_rmatch(v7, ">2.0.1")) semvers_unshift(semvers, v7); - if (semver_rmatch(v8, ">2.0.1")) semvers_push(semvers, v8); - if (semver_rmatch(v9, ">2.0.1")) semvers_unshift(semvers, v9); - if (semver_rmatch(v10, ">2.0.1")) semvers_push(semvers, v10); - if (semver_rmatch(v0, ">2.0.1")) semvers_push(semvers, v0); - if (semver_rmatch(v1, ">2.0.1")) semvers_unshift(semvers, v1); - if (semver_rmatch(v2, ">2.0.1")) semvers_push(semvers, v2); - if (semver_rmatch(v3, ">2.0.1")) semvers_unshift(semvers, v3); - if (semver_rmatch(v4, ">2.0.1")) semvers_push(semvers, v4); - if (semver_rmatch(v5, ">2.0.1")) semvers_unshift(semvers, v5); - if (semver_rmatch(v6, ">2.0.1")) semvers_push(semvers, v6); - if (semver_rmatch(v7, ">2.0.1")) semvers_unshift(semvers, v7); - if (semver_rmatch(v8, ">2.0.1")) semvers_push(semvers, v8); - if (semver_rmatch(v9, ">2.0.1")) semvers_unshift(semvers, v9); - if (semver_rmatch(v10, ">2.0.1")) semvers_push(semvers, v10); - - if (semvers.length != 18) { - return EXIT_FAILURE; - } - if (semvers.capacity != 32) { - return EXIT_FAILURE; - } - - semvers_sort(semvers); - - for (unsigned i = 0; i < semvers.length; ++i) { - semver_fwrite(semvers.data + i, stdout); - putc('\n', stdout); - } - - v0 = semvers_pop(semvers); - v1 = semvers_shift(semvers); - - assert(memcmp("v2.1", v0.raw, v0.len) == 0); - assert(memcmp("v2.0.2", v1.raw, v1.len) == 0 || memcmp("2.0.2", v1.raw, v1.len) == 0); - - semvers_rsort(semvers); - putc('\n', stdout); - for (unsigned i = 0; i < semvers.length; ++i) { - semver_fwrite(semvers.data + i, stdout); - putc('\n', stdout); - } - - semvers_dtor(semvers); - - return EXIT_SUCCESS; -} diff --git a/core/src/sv/test/usage.c b/core/src/sv/test/usage.c deleted file mode 100644 index 818608137..000000000 --- a/core/src/sv/test/usage.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This is free and unencumbered software released into the public domain. - * - * Anyone is free to copy, modify, publish, use, compile, sell, or - * distribute this software, either in source code form or as a compiled - * binary, for any purpose, commercial or non-commercial, and by any - * means. - * - * In jurisdictions that recognize copyright laws, the author or authors - * of this software dedicate any and all copyright interest in the - * software to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and - * successors. We intend this dedication to be an overt act of - * relinquishment in perpetuity of all present and future rights to this - * software under copyright law. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * For more information, please refer to <http://unlicense.org> - */ - -#include <stdlib.h> -#include <assert.h> - -#include "semver.h" - -int main(void) { - semver_t semver = {0}; - - semver(&semver, "v1.2.3-alpha.1"); - - assert(1 == semver.major); - assert(2 == semver.minor); - assert(3 == semver.patch); - assert(0 == memcmp("alpha", semver.prerelease.raw, sizeof("alpha")-1)); - assert(0 == memcmp("1", semver.prerelease.next->raw, sizeof("1")-1)); - assert(true == semver_rmatch(semver, "1.2.1 || >=1.2.3-alpha <1.2.5")); - - semver_dtor(&semver); -} diff --git a/core/src/sv/test/utils.c b/core/src/sv/test/utils.c deleted file mode 100644 index 89ae4cd1b..000000000 --- a/core/src/sv/test/utils.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This is free and unencumbered software released into the public domain. - * - * Anyone is free to copy, modify, publish, use, compile, sell, or - * distribute this software, either in source code form or as a compiled - * binary, for any purpose, commercial or non-commercial, and by any - * means. - * - * In jurisdictions that recognize copyright laws, the author or authors - * of this software dedicate any and all copyright interest in the - * software to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and - * successors. We intend this dedication to be an overt act of - * relinquishment in perpetuity of all present and future rights to this - * software under copyright law. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * For more information, please refer to <http://unlicense.org> - */ - -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include "semver.h" - -int test_version_fwrite(void) { - static const char input_str[] = "1.2.3-alpha.1+x86-64"; - semver_t version; - int rv; - - rv = semver(&version, input_str); - if (0 == rv) { - printf("test_version_fwrite: "); - semver_fwrite(&version, stdout); - if (0 == errno) { - printf("\n"); - rv = 0; - } - } - semver_dtor(&version); - return rv; -} - -int test_comparator_fwrite(void) { - static const char input_str[] = "<=1.2.3"; - semver_comp_t comp; - int rv; - - rv = semver_comp(&comp, input_str); - if (0 == rv) { - printf("test_comparator_fwrite: "); - semver_comp_fwrite(&comp, stdout); - if (0 == errno) { - printf("\n"); - rv = 0; - } - } - semver_comp_dtor(&comp); - return rv; -} - -int test_range_fwrite(void) { - static const char input_str[] = ">=1.2.3 <4.0.0"; - semver_range_t range; - int rv; - - rv = semver_range(&range, input_str); - if (0 == rv) { - printf("test_range_fwrite: "); - semver_range_fwrite(&range, stdout); - if (0 == errno) { - printf("\n"); - rv = 0; - } - } - semver_range_dtor(&range); - return rv; -} - -int main(void) { - if (test_version_fwrite()) { - return EXIT_FAILURE; - } - - if (test_comparator_fwrite()) { - return EXIT_FAILURE; - } - - if (test_range_fwrite()) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/core/src/sv/test/version.c b/core/src/sv/test/version.c deleted file mode 100644 index a10b6e645..000000000 --- a/core/src/sv/test/version.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * This is free and unencumbered software released into the public domain. - * - * Anyone is free to copy, modify, publish, use, compile, sell, or - * distribute this software, either in source code form or as a compiled - * binary, for any purpose, commercial or non-commercial, and by any - * means. - * - * In jurisdictions that recognize copyright laws, the author or authors - * of this software dedicate any and all copyright interest in the - * software to the public domain. We make this dedication for the benefit - * of the public at large and to the detriment of our heirs and - * successors. We intend this dedication to be an overt act of - * relinquishment in perpetuity of all present and future rights to this - * software under copyright law. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * For more information, please refer to <http://unlicense.org> - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "semver.h" - -#define STRNSIZE(s) (s), sizeof(s)-1 - -int test_read(const char *expected, const char *str, size_t len) { - unsigned slen; - char buffer[1024]; - semver_t semver = {0}; - - printf("test: `%.*s`", (int) len, str); - if (semvern(&semver, str, len)) { - puts(" \tcouldn't parse"); - return 1; - } - slen = (unsigned) semver_write(semver, buffer, 1024); - printf(" \t=> \t`%.*s`", slen, buffer); - if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { - printf(" != `%s`\n", expected); - semver_dtor(&semver); - return 1; - } - printf(" == `%s`\n", expected); - semver_dtor(&semver); - return 0; -} - -int test_try_read(const char *expected, const char *str, size_t len) { - unsigned slen; - char buffer[1024]; - semver_t semver = {0}; - - printf("test: `%.*s`", (int) len, str); - if (semver_tryn(&semver, str, len)) { - puts(" \tcouldn't parse"); - return 1; - } - slen = (unsigned) semver_write(semver, buffer, 1024); - printf(" \t=> \t`%.*s`", slen, buffer); - if (memcmp(expected, buffer, (size_t) slen > len ? slen : len) != 0) { - printf(" != `%s`\n", expected); - semver_dtor(&semver); - return 1; - } - printf(" == `%s`\n", expected); - semver_dtor(&semver); - return 0; -} - -int main(void) { - puts("normal:"); - if (test_read("0.2.3", STRNSIZE("0.2.3"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3", STRNSIZE("1.2.3"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3-alpha", STRNSIZE("v1.2.3-alpha"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3-alpha.2", STRNSIZE("1.2.3-alpha.2"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3+77", STRNSIZE("v1.2.3+77"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3+0", STRNSIZE("v1.2.3+0"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3+77.2", STRNSIZE("1.2.3+77.2"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3-alpha.2+77", STRNSIZE("v1.2.3-alpha.2+77"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3-alpha.2+77.2", STRNSIZE("1.2.3-alpha.2+77.2"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3-al-pha.2+77", STRNSIZE("v1.2.3-al-pha.2+77"))) { - return EXIT_FAILURE; - } - if (test_read("1.2.3-al-pha.2+77.2", STRNSIZE("1.2.3-al-pha.2+77.2"))) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("vv1.2.3")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("v1.2")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("v1.2.x")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("v1.2.3-")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("v1.2.3+")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("v1.2.3+01")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("v0.01.3")) == 0) { - return EXIT_FAILURE; - } - if (test_read("", STRNSIZE("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget " - "dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascet" - "ur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, s")) - == 0) { - return EXIT_FAILURE; - } - - puts("try:"); - if (test_try_read("0.2.3", STRNSIZE("0.2.3"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3", STRNSIZE("1.2.3"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3-alpha", STRNSIZE("v1.2.3-alpha"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3-alpha.2", STRNSIZE("1.2.3-alpha.2"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3+77", STRNSIZE("v1.2.3+77"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3+0", STRNSIZE("v1.2.3+0"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3+77.2", STRNSIZE("1.2.3+77.2"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3-alpha.2+77", STRNSIZE("v1.2.3-alpha.2+77"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3-alpha.2+77.2", STRNSIZE("1.2.3-alpha.2+77.2"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3-al-pha.2+77", STRNSIZE("v1.2.3-al-pha.2+77"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3-al-pha.2+77.2", STRNSIZE("1.2.3-al-pha.2+77.2"))) { - return EXIT_FAILURE; - } - if (test_try_read("", STRNSIZE("")) == 0) { - return EXIT_FAILURE; - } - if (test_try_read("", STRNSIZE("vv1.2.3")) == 0) { - return EXIT_FAILURE; - } - if (test_try_read("", STRNSIZE("v1.2")) == 0) { - return EXIT_FAILURE; - } - if (test_try_read("", STRNSIZE("v1.2.x")) == 0) { - return EXIT_FAILURE; - } - if (test_try_read("", STRNSIZE("v1.2.3-")) == 0) { - return EXIT_FAILURE; - } - if (test_try_read("", STRNSIZE("v1.2.3+")) == 0) { - return EXIT_FAILURE; - } - if (test_try_read("", STRNSIZE("v1.2.3+01")) == 0) { - return EXIT_FAILURE; - } - if (test_try_read("", STRNSIZE("v0.01.3")) == 0) { - return EXIT_FAILURE; - } - if (test_try_read("", STRNSIZE("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget " - "dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascet" - "ur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, s")) - == 0) { - return EXIT_FAILURE; - } - if (test_try_read("0.2.0", STRNSIZE("0.2"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.0.0", STRNSIZE("v1"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.0-alpha", STRNSIZE("v1.2alpha"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3-alpha.2", STRNSIZE("1.2.3alpha.2"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.0.0+77", STRNSIZE("v1+77"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.0+0", STRNSIZE("v1.2+0"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.0.0+77.2", STRNSIZE("v1+77.2"))) { - return EXIT_FAILURE; - } - if (test_try_read("1.2.3-alpha.2+77", STRNSIZE("v1.2.3alpha.2+77"))) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/core/src/sv/test/xmake.lua b/core/src/sv/test/xmake.lua deleted file mode 100644 index 4169560e8..000000000 --- a/core/src/sv/test/xmake.lua +++ /dev/null @@ -1,45 +0,0 @@ -set_default(false) -set_languages("c99") -set_kind("binary") -add_deps("sv") -add_links("sv") -add_includedirs("../include") -add_linkdirs("$(buildir)") - -target("version_test") - add_files("version.c") - -target("comp_test") - add_files("comp.c") - -target("range_test") - add_files("range.c") - -target("match_test") - add_files("match.c") - -target("semvers_test") - add_files("semvers.c") - -target("utils_test") - add_files("utils.c") - -target("usage_test") - add_files("usage.c") - -task("check") - on_run(function () - import("core.project.task") - task.run("run", {target = "version_test"}) - task.run("run", {target = "comp_test"}) - task.run("run", {target = "range_test"}) - task.run("run", {target = "match_test"}) - task.run("run", {target = "semvers_test"}) - task.run("run", {target = "utils_test"}) - task.run("run", {target = "usage_test"}) - end) - set_menu { - usage = "xmake check" - , description = "Run tests !" - , options = {} - } diff --git a/core/src/tbox/src/tbox/asio/asio.h b/core/src/tbox/src/tbox/asio/asio.h deleted file mode 100644 index bb4f1ea7d..000000000 --- a/core/src/tbox/src/tbox/asio/asio.h +++ /dev/null @@ -1,36 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file asio.h - * - */ -#ifndef TB_ASIO_H -#define TB_ASIO_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#ifdef TB_CONFIG_API_HAVE_DEPRECATED -# include "deprecated/deprecated.h" -#endif - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/aice.h b/core/src/tbox/src/tbox/asio/deprecated/aice.h deleted file mode 100644 index 90a4ea661..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aice.h +++ /dev/null @@ -1,484 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aice.h - * @ingroup asio - */ -#ifndef TB_ASIO_AICE_H -#define TB_ASIO_AICE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "aico.h" -#include "../../network/ipaddr.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the aice code enum -typedef enum __tb_aice_code_e -{ - TB_AICE_CODE_NONE = 0 - -, TB_AICE_CODE_ACPT = 1 //!< for sock, accept it -, TB_AICE_CODE_CONN = 2 //!< for sock, connect to the host address -, TB_AICE_CODE_RECV = 3 //!< for sock, recv data for tcp -, TB_AICE_CODE_SEND = 4 //!< for sock, send data for tcp -, TB_AICE_CODE_URECV = 5 //!< for sock, recv data for udp -, TB_AICE_CODE_USEND = 6 //!< for sock, send data for udp -, TB_AICE_CODE_RECVV = 7 //!< for sock, recv iovec data for tcp -, TB_AICE_CODE_SENDV = 8 //!< for sock, send iovec data for tcp -, TB_AICE_CODE_URECVV = 9 //!< for sock, recv iovec data for udp -, TB_AICE_CODE_USENDV = 10 //!< for sock, send iovec data for udp -, TB_AICE_CODE_SENDF = 11 //!< for sock, maybe return TB_STATE_NOT_SUPPORTED - -, TB_AICE_CODE_READ = 12 //!< for file, read data -, TB_AICE_CODE_WRIT = 13 //!< for file, writ data -, TB_AICE_CODE_READV = 14 //!< for file, read iovec data -, TB_AICE_CODE_WRITV = 15 //!< for file, writ iovec data -, TB_AICE_CODE_FSYNC = 16 //!< for file, flush data to file - -, TB_AICE_CODE_RUNTASK = 17 //!< for task or sock or file, run task with the given delay -, TB_AICE_CODE_CLOS = 18 //!< for task or sock or file - -, TB_AICE_CODE_MAXN = 19 - -}tb_aice_code_e; - -/// the acpt aice type -typedef struct __tb_aice_acpt_t -{ - /// the client aico - tb_aico_ref_t aico; - - /// the client addr - tb_ipaddr_t addr; - - /// the private data for using the left space of the union - tb_cpointer_t priv[1]; - -}tb_aice_acpt_t; - -/// the conn aice type -typedef struct __tb_aice_conn_t -{ - /// the addr - tb_ipaddr_t addr; - -}tb_aice_conn_t; - -#ifdef TB_CONFIG_OS_WINDOWS -/// the recv aice type, base: tb_iovec_t -typedef struct __tb_aice_recv_t -{ - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the recv data for (tb_iovec_t*)->data - tb_byte_t* data; - - /// the data real - tb_size_t real; - -}tb_aice_recv_t; - -/// the send aice type, base: tb_iovec_t -typedef struct __tb_aice_send_t -{ - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the send data for (tb_iovec_t*)->data - tb_byte_t const* data; - - /// the data real - tb_size_t real; - -}tb_aice_send_t; - -/// the urecv aice type, base: tb_iovec_t -typedef struct __tb_aice_urecv_t -{ - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the recv data for (tb_iovec_t*)->data - tb_byte_t* data; - - /// the data real - tb_size_t real; - - /// the addr - tb_ipaddr_t addr; - -}tb_aice_urecv_t; - -/// the usend aice type, base: tb_iovec_t -typedef struct __tb_aice_usend_t -{ - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the send data for (tb_iovec_t*)->data - tb_byte_t const* data; - - /// the data real - tb_size_t real; - - /// the peer addr - tb_ipaddr_t addr; - -}tb_aice_usend_t; - -/// the read aice type, base: tb_iovec_t -typedef struct __tb_aice_read_t -{ - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the read data for (tb_iovec_t*)->data - tb_byte_t* data; - - /// the data real - tb_size_t real; - - /// the file seek - tb_hize_t seek; - -}tb_aice_read_t; - -/// the writ aice type, base: tb_iovec_t -typedef struct __tb_aice_writ_t -{ - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the writ data for (tb_iovec_t*)->data - tb_byte_t const* data; - - /// the data real - tb_size_t real; - - /// the file seek - tb_hize_t seek; - -}tb_aice_writ_t; -#else -/// the recv aice type, base: tb_iovec_t -typedef struct __tb_aice_recv_t -{ - /// the recv data for (tb_iovec_t*)->data - tb_byte_t* data; - - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the data real - tb_size_t real; - -}tb_aice_recv_t; - -/// the send aice type, base: tb_iovec_t -typedef struct __tb_aice_send_t -{ - /// the send data for (tb_iovec_t*)->data - tb_byte_t const* data; - - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the data real - tb_size_t real; - -}tb_aice_send_t; - -/// the urecv aice type, base: tb_iovec_t -typedef struct __tb_aice_urecv_t -{ - /// the recv data for (tb_iovec_t*)->data - tb_byte_t* data; - - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the data real - tb_size_t real; - - /// the addr - tb_ipaddr_t addr; - -}tb_aice_urecv_t; - -/// the usend aice type, base: tb_iovec_t -typedef struct __tb_aice_usend_t -{ - /// the send data for (tb_iovec_t*)->data - tb_byte_t const* data; - - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the data real - tb_size_t real; - - /// the addr - tb_ipaddr_t addr; - -}tb_aice_usend_t; - -/// the read aice type, base: tb_iovec_t -typedef struct __tb_aice_read_t -{ - /// the read data for (tb_iovec_t*)->data - tb_byte_t* data; - - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the data real - tb_size_t real; - - /// the file seek - tb_hize_t seek; - -}tb_aice_read_t; - -/// the writ aice type, base: tb_iovec_t -typedef struct __tb_aice_writ_t -{ - /// the writ data for (tb_iovec_t*)->data - tb_byte_t const* data; - - /// the data size for (tb_iovec_t*)->size - tb_iovec_size_t size; - - /// the data real - tb_size_t real; - - /// the file seek - tb_hize_t seek; - -}tb_aice_writ_t; -#endif - -/// the recvv aice type -typedef struct __tb_aice_recvv_t -{ - /// the recv list - tb_iovec_t const* list; - - /// the list size - tb_size_t size; - - /// the data real - tb_size_t real; - -}tb_aice_recvv_t; - -/// the sendv aice type -typedef struct __tb_aice_sendv_t -{ - /// the send list - tb_iovec_t const* list; - - /// the list size - tb_size_t size; - - /// the data real - tb_size_t real; - -}tb_aice_sendv_t; - -/// the urecvv aice type -typedef struct __tb_aice_urecvv_t -{ - /// the recv list - tb_iovec_t const* list; - - /// the list size - tb_size_t size; - - /// the data real - tb_size_t real; - - /// the peer addr - tb_ipaddr_t addr; - -}tb_aice_urecvv_t; - -/// the usendv aice type -typedef struct __tb_aice_usendv_t -{ - /// the send list - tb_iovec_t const* list; - - /// the list size - tb_size_t size; - - /// the data real - tb_size_t real; - - /// the addr - tb_ipaddr_t addr; - -}tb_aice_usendv_t; - -/// the sendf aice type -typedef struct __tb_aice_sendf_t -{ - /// the file - tb_file_ref_t file; - - /// the private data for using the left space of the union - tb_handle_t priv[1]; - - /// the real - tb_size_t real; - - /// the size - tb_hize_t size; - - /// the seek - tb_hize_t seek; - -}tb_aice_sendf_t; - -/// the readv aice type -typedef struct __tb_aice_readv_t -{ - /// the read list - tb_iovec_t const* list; - - /// the list size - tb_size_t size; - - /// the data real - tb_size_t real; - - /// the file seek - tb_hize_t seek; - -}tb_aice_readv_t; - -/// the writv aice type -typedef struct __tb_aice_writv_t -{ - /// the writ list - tb_iovec_t const* list; - - /// the list size - tb_size_t size; - - /// the data real - tb_size_t real; - - /// the file seek - tb_hize_t seek; - -}tb_aice_writv_t; - -/// the runtask aice type -typedef struct __tb_aice_runtask_t -{ - /// the when - tb_hize_t when; - - /// the delay - tb_size_t delay; - -}tb_aice_runtask_t; - -/// the aice type -typedef struct __tb_aice_t -{ - /// the aice code - tb_uint8_t code; - - /*! the state - * - * TB_STATE_OK - * TB_STATE_FAILED - * TB_STATE_KILLED - * TB_STATE_CLOSED - * TB_STATE_PENDING - * TB_STATE_TIMEOUT - * TB_STATE_NOT_SUPPORTED - */ - tb_size_t state; - - /// the aico func - tb_aico_func_t func; - - /// the aico private data - tb_cpointer_t priv; - - /// the aico - tb_aico_ref_t aico; - - /*! the events - * - * tb_iovec_t must be aligned by cpu-bytes for windows WSABUF - */ -#ifdef TB_CONFIG_OS_WINDOWS - __tb_cpu_aligned__ union -#else - union -#endif - { - // for sock - tb_aice_acpt_t acpt; - tb_aice_conn_t conn; - tb_aice_recv_t recv; - tb_aice_send_t send; - tb_aice_urecv_t urecv; - tb_aice_usend_t usend; - tb_aice_recvv_t recvv; - tb_aice_sendv_t sendv; - tb_aice_urecvv_t urecvv; - tb_aice_usendv_t usendv; - tb_aice_sendf_t sendf; - - // for file - tb_aice_read_t read; - tb_aice_writ_t writ; - tb_aice_readv_t readv; - tb_aice_writv_t writv; - - // for task - tb_aice_runtask_t runtask; - - } u; - -}tb_aice_t, *tb_aice_ref_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/aico.c b/core/src/tbox/src/tbox/asio/deprecated/aico.c deleted file mode 100644 index 2731f7015..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aico.c +++ /dev/null @@ -1,1082 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aico.c - * @ingroup asio - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "aico" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "aico.h" -#include "aicp.h" -#include "impl/prefix.h" -#include "../../platform/platform.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_aico_ref_t tb_aico_init(tb_aicp_ref_t aicp) -{ - // check - tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)aicp; - tb_assert_and_check_return_val(aicp_impl && aicp_impl->pool, tb_null); - - // enter - tb_spinlock_enter(&aicp_impl->lock); - - // make aico - tb_aico_impl_t* aico = (tb_aico_impl_t*)tb_fixed_pool_malloc0(aicp_impl->pool); - - // init aico - if (aico) - { - aico->aicp = aicp; - aico->type = TB_AICO_TYPE_NONE; - aico->handle = tb_null; - aico->state = TB_STATE_CLOSED; - - // init timeout - tb_size_t i = 0; - tb_size_t n = tb_arrayn(aico->timeout); - for (i = 0; i < n; i++) aico->timeout[i] = -1; - } - - // leave - tb_spinlock_leave(&aicp_impl->lock); - - // ok? - return (tb_aico_ref_t)aico; -} -tb_bool_t tb_aico_open_sock(tb_aico_ref_t aico, tb_socket_ref_t sock) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp; - tb_assert_and_check_return_val(impl && sock && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->addo, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // closed? - tb_assert_and_check_break(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); - tb_assert_and_check_break(!impl->type && !impl->handle); - - // bind type and handle - impl->type = TB_AICO_TYPE_SOCK; - impl->handle = (tb_handle_t)sock; - - // addo aico - ok = aicp_impl->ptor->addo(aicp_impl->ptor, impl); - tb_assert_and_check_break(ok); - - // opened - tb_atomic_set(&impl->state, TB_STATE_OPENED); - - } while (0); - - // ok? - return ok; -} -tb_bool_t tb_aico_open_sock_from_type(tb_aico_ref_t aico, tb_size_t type, tb_size_t family) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp; - tb_assert_and_check_return_val(impl && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->addo, tb_false); - - // done - tb_bool_t ok = tb_false; - tb_socket_ref_t sock = tb_null; - do - { - // closed? - tb_assert_and_check_break(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); - tb_assert_and_check_break(!impl->type && !impl->handle); - - // init sock - sock = tb_socket_init(type, family); - tb_assert_and_check_break(sock); - - // bind type and handle - impl->type = TB_AICO_TYPE_SOCK; - impl->handle = (tb_handle_t)sock; - - // addo aico - ok = aicp_impl->ptor->addo(aicp_impl->ptor, impl); - tb_assert_and_check_break(ok); - - // opened - tb_atomic_set(&impl->state, TB_STATE_OPENED); - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (sock) tb_socket_exit(sock); - sock = tb_null; - } - - // ok? - return ok; -} -tb_bool_t tb_aico_open_file(tb_aico_ref_t aico, tb_file_ref_t file) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp; - tb_assert_and_check_return_val(impl && file && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->addo, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // closed? - tb_assert_and_check_break(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); - tb_assert_and_check_break(!impl->type && !impl->handle); - - // bind type and handle - impl->type = TB_AICO_TYPE_FILE; - impl->handle = (tb_handle_t)file; - - // addo aico - ok = aicp_impl->ptor->addo(aicp_impl->ptor, impl); - tb_assert_and_check_break(ok); - - // opened - tb_atomic_set(&impl->state, TB_STATE_OPENED); - - } while (0); - - // ok? - return ok; -} -tb_bool_t tb_aico_open_file_from_path(tb_aico_ref_t aico, tb_char_t const* path, tb_size_t mode) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp; - tb_assert_and_check_return_val(impl && path && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->addo, tb_false); - - // done - tb_bool_t ok = tb_false; - tb_file_ref_t file = tb_null; - do - { - // closed? - tb_assert_and_check_break(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); - tb_assert_and_check_break(!impl->type && !impl->handle); - - // init file - file = tb_file_init(path, mode | TB_FILE_MODE_ASIO); - tb_assert_and_check_break(file); - - // bind type and handle - impl->type = TB_AICO_TYPE_FILE; - impl->handle = (tb_handle_t)file; - - // addo aico - ok = aicp_impl->ptor->addo(aicp_impl->ptor, impl); - tb_assert_and_check_break(ok); - - // opened - tb_atomic_set(&impl->state, TB_STATE_OPENED); - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (file) tb_file_exit(file); - file = tb_null; - } - - // ok? - return ok; -} -tb_bool_t tb_aico_open_task(tb_aico_ref_t aico, tb_bool_t ltimer) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp; - tb_assert_and_check_return_val(impl && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->addo, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // closed? - tb_assert_and_check_break(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); - tb_assert_and_check_break(!impl->type); - - // bind type and handle - // hack: handle != null? using higher precision timer for being compatible with sock/file task - impl->type = TB_AICO_TYPE_TASK; - impl->handle = (tb_handle_t)(tb_size_t)!ltimer; - - // addo aico - ok = aicp_impl->ptor->addo(aicp_impl->ptor, impl); - tb_assert_and_check_break(ok); - - // opened - tb_atomic_set(&impl->state, TB_STATE_OPENED); - - } while (0); - - // ok? - return ok; -} -tb_void_t tb_aico_exit(tb_aico_ref_t aico) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp; - tb_assert_and_check_return(impl && aicp_impl && aicp_impl->pool); - - // wait closing? - tb_size_t tryn = 15; - while (tb_atomic_get(&impl->state) != TB_STATE_CLOSED && tryn--) - { - // trace - tb_trace_d("exit[%p]: type: %lu, handle: %p, state: %s: wait: ..", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&impl->state))); - - // wait some time - tb_msleep(200); - } - - // check - tb_assert(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); - tb_check_return(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); - - // enter - tb_spinlock_enter(&aicp_impl->lock); - - // trace - tb_trace_d("exit[%p]: type: %lu, handle: %p, state: %s: ok", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&impl->state))); - - // free it - tb_fixed_pool_free(aicp_impl->pool, aico); - - // leave - tb_spinlock_leave(&aicp_impl->lock); -} -tb_void_t tb_aico_kill(tb_aico_ref_t aico) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp; - tb_assert_and_check_return(impl && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->kilo); - - // the impl is killed and not worked? - tb_check_return(!tb_atomic_get(&aicp_impl->kill) || tb_atomic_get(&aicp_impl->work)); - - // trace - tb_trace_d("kill: aico[%p]: type: %lu, handle: %p: state: %s: ..", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&((tb_aico_impl_t*)aico)->state))); - - // opened? killed - if (TB_STATE_OPENED == tb_atomic_fetch_and_pset(&impl->state, TB_STATE_OPENED, TB_STATE_KILLED)) - { - // trace - tb_trace_d("kill: aico[%p]: type: %lu, handle: %p: ok", aico, tb_aico_type(aico), impl->handle); - } - // pending? kill it - else if (TB_STATE_PENDING == tb_atomic_fetch_and_pset(&impl->state, TB_STATE_PENDING, TB_STATE_KILLING)) - { - // kill aico - aicp_impl->ptor->kilo(aicp_impl->ptor, impl); - - // trace - tb_trace_d("kill: aico[%p]: type: %lu, handle: %p: state: pending: ok", aico, tb_aico_type(aico), impl->handle); - } -} -tb_aicp_ref_t tb_aico_aicp(tb_aico_ref_t aico) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl, tb_null); - - // the impl aicp - return impl->aicp; -} -tb_size_t tb_aico_type(tb_aico_ref_t aico) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl, TB_AICO_TYPE_NONE); - - // the impl type - return impl->type; -} -tb_socket_ref_t tb_aico_sock(tb_aico_ref_t aico) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->type == TB_AICO_TYPE_SOCK, tb_null); - - // the socket handle - return (tb_socket_ref_t)impl->handle; -} -tb_file_ref_t tb_aico_file(tb_aico_ref_t aico) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->type == TB_AICO_TYPE_FILE, tb_null); - - // the file handle - return (tb_file_ref_t)impl->handle; -} -tb_long_t tb_aico_timeout(tb_aico_ref_t aico, tb_size_t type) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && type < tb_arrayn(impl->timeout), -1); - - // the impl timeout - return tb_atomic_get((tb_atomic_t*)(impl->timeout + type)); -} -tb_void_t tb_aico_timeout_set(tb_aico_ref_t aico, tb_size_t type, tb_long_t timeout) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return(impl && type < tb_arrayn(impl->timeout)); - - // set the impl timeout - tb_atomic_set((tb_atomic_t*)(impl->timeout + type), timeout); -} -tb_bool_t tb_aico_clos_try(tb_aico_ref_t aico) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp, tb_false); - - // closed? - return (tb_atomic_get(&impl->state) == TB_STATE_CLOSED)? tb_true : tb_false; -} -tb_bool_t tb_aico_clos_(tb_aico_ref_t aico, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_CLOS; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - - // closed? - if (tb_aico_clos_try(aico)) - { - // close ok - aice.state = TB_STATE_OK; - - // done func directly - func(&aice); - - // ok - return tb_true; - } - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_acpt_(tb_aico_ref_t aico, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_ACPT; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_conn_(tb_aico_ref_t aico, tb_ipaddr_ref_t addr, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && addr, tb_false); - - // check address - tb_assert(!tb_ipaddr_is_empty(addr)); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_CONN; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - tb_ipaddr_copy(&aice.u.conn.addr, addr); - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_recv_(tb_aico_ref_t aico, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_RECV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.recv.data = data; - aice.u.recv.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_send_(tb_aico_ref_t aico, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_SEND; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.send.data = data; - aice.u.send.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_urecv_(tb_aico_ref_t aico, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_URECV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.urecv.data = data; - aice.u.urecv.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_usend_(tb_aico_ref_t aico, tb_ipaddr_ref_t addr, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && addr && data && size, tb_false); - - // check address - tb_assert(!tb_ipaddr_is_empty(addr)); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_USEND; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.usend.data = data; - aice.u.usend.size = (tb_iovec_size_t)size; - tb_ipaddr_copy(&aice.u.usend.addr, addr); - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_recvv_(tb_aico_ref_t aico, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_RECVV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.recvv.list = list; - aice.u.recvv.size = size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_sendv_(tb_aico_ref_t aico, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_SENDV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.sendv.list = list; - aice.u.sendv.size = size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_urecvv_(tb_aico_ref_t aico, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && addr && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_URECVV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.urecvv.list = list; - aice.u.urecvv.size = size; - tb_ipaddr_copy(&aice.u.urecvv.addr, addr); - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_usendv_(tb_aico_ref_t aico, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && addr && list && size, tb_false); - - // check address - tb_assert(!tb_ipaddr_is_empty(addr)); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_USENDV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.usendv.list = list; - aice.u.usendv.size = size; - tb_ipaddr_copy(&aice.u.usendv.addr, addr); - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_sendf_(tb_aico_ref_t aico, tb_file_ref_t file, tb_hize_t seek, tb_hize_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && file, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_SENDF; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.sendf.file = file; - aice.u.sendf.seek = seek; - aice.u.sendf.size = size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_read_(tb_aico_ref_t aico, tb_hize_t seek, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_READ; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.read.seek = seek; - aice.u.read.data = data; - aice.u.read.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_writ_(tb_aico_ref_t aico, tb_hize_t seek, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_WRIT; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.writ.seek = seek; - aice.u.writ.data = data; - aice.u.writ.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_readv_(tb_aico_ref_t aico, tb_hize_t seek, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_READV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.readv.seek = seek; - aice.u.readv.list = list; - aice.u.readv.size = size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_writv_(tb_aico_ref_t aico, tb_hize_t seek, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_WRITV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.writv.seek = seek; - aice.u.writv.list = list; - aice.u.writv.size = size; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_fsync_(tb_aico_ref_t aico, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_FSYNC; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_clos_after_(tb_aico_ref_t aico, tb_size_t delay, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_CLOS; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_acpt_after_(tb_aico_ref_t aico, tb_size_t delay, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_ACPT; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_conn_after_(tb_aico_ref_t aico, tb_size_t delay, tb_ipaddr_ref_t addr, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && addr, tb_false); - - // check address - tb_assert(!tb_ipaddr_is_empty(addr)); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_CONN; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - tb_ipaddr_copy(&aice.u.conn.addr, addr); - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_recv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_RECV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.recv.data = data; - aice.u.recv.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_send_after_(tb_aico_ref_t aico, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_SEND; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.send.data = data; - aice.u.send.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_urecv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_URECV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.urecv.data = data; - aice.u.urecv.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_usend_after_(tb_aico_ref_t aico, tb_size_t delay, tb_ipaddr_ref_t addr, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && addr && data && size, tb_false); - - // check address - tb_assert(!tb_ipaddr_is_empty(addr)); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_USEND; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.usend.data = data; - aice.u.usend.size = (tb_iovec_size_t)size; - tb_ipaddr_copy(&aice.u.usend.addr, addr); - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_recvv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_RECVV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.recvv.list = list; - aice.u.recvv.size = size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_sendv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_SENDV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.sendv.list = list; - aice.u.sendv.size = size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_urecvv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && addr && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_URECVV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.urecvv.list = list; - aice.u.urecvv.size = size; - tb_ipaddr_copy(&aice.u.urecvv.addr, addr); - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_usendv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && addr && list && size, tb_false); - - // check address - tb_assert(!tb_ipaddr_is_empty(addr)); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_USENDV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.usendv.list = list; - aice.u.usendv.size = size; - tb_ipaddr_copy(&aice.u.usendv.addr, addr); - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_sendf_after_(tb_aico_ref_t aico, tb_size_t delay, tb_file_ref_t file, tb_hize_t seek, tb_hize_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && file, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_SENDF; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.sendf.file = file; - aice.u.sendf.seek = seek; - aice.u.sendf.size = size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_read_after_(tb_aico_ref_t aico, tb_size_t delay, tb_hize_t seek, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_READ; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.read.seek = seek; - aice.u.read.data = data; - aice.u.read.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_writ_after_(tb_aico_ref_t aico, tb_size_t delay, tb_hize_t seek, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && data && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_WRIT; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.writ.seek = seek; - aice.u.writ.data = data; - aice.u.writ.size = (tb_iovec_size_t)size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_readv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_hize_t seek, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_READV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.readv.seek = seek; - aice.u.readv.list = list; - aice.u.readv.size = size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_writv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_hize_t seek, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp && list && size, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_WRITV; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.writv.seek = seek; - aice.u.writv.list = list; - aice.u.writv.size = size; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_fsync_after_(tb_aico_ref_t aico, tb_size_t delay, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_FSYNC; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - - // post - return tb_aicp_post_after_(impl->aicp, delay, &aice __tb_debug_args__); -} -tb_bool_t tb_aico_task_run_(tb_aico_ref_t aico, tb_size_t delay, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__) -{ - // check - tb_aico_impl_t* impl = (tb_aico_impl_t*)aico; - tb_assert_and_check_return_val(impl && impl->aicp, tb_false); - - // init - tb_aice_t aice = {0}; - aice.code = TB_AICE_CODE_RUNTASK; - aice.state = TB_STATE_PENDING; - aice.func = func; - aice.priv = priv; - aice.aico = aico; - aice.u.runtask.when = tb_cache_time_mclock() + delay; - aice.u.runtask.delay = delay; - - // post - return tb_aicp_post_(impl->aicp, &aice __tb_debug_args__); -} - diff --git a/core/src/tbox/src/tbox/asio/deprecated/aico.h b/core/src/tbox/src/tbox/asio/deprecated/aico.h deleted file mode 100644 index c7c32201d..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aico.h +++ /dev/null @@ -1,733 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aico.h - * @ingroup asio - * - */ -#ifndef TB_ASIO_AICO_H -#define TB_ASIO_AICO_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "../../network/ipaddr.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ -#define tb_aico_clos(aico, func, priv) tb_aico_clos_(aico, func, priv __tb_debug_vals__) -#define tb_aico_acpt(aico, func, priv) tb_aico_acpt_(aico, func, priv __tb_debug_vals__) -#define tb_aico_conn(aico, addr, func, priv) tb_aico_conn_(aico, addr, func, priv __tb_debug_vals__) -#define tb_aico_recv(aico, data, size, func, priv) tb_aico_recv_(aico, data, size, func, priv __tb_debug_vals__) -#define tb_aico_send(aico, data, size, func, priv) tb_aico_send_(aico, data, size, func, priv __tb_debug_vals__) -#define tb_aico_urecv(aico, data, size, func, priv) tb_aico_urecv_(aico, data, size, func, priv __tb_debug_vals__) -#define tb_aico_usend(aico, addr, data, size, func, priv) tb_aico_usend_(aico, addr, data, size, func, priv __tb_debug_vals__) -#define tb_aico_recvv(aico, list, size, func, priv) tb_aico_recvv_(aico, list, size, func, priv __tb_debug_vals__) -#define tb_aico_sendv(aico, list, size, func, priv) tb_aico_sendv_(aico, list, size, func, priv __tb_debug_vals__) -#define tb_aico_urecvv(aico, addr, list, size, func, priv) tb_aico_urecvv_(aico, addr, list, size, func, priv __tb_debug_vals__) -#define tb_aico_usendv(aico, addr, list, size, func, priv) tb_aico_usendv_(aico, addr, list, size, func, priv __tb_debug_vals__) -#define tb_aico_sendf(aico, file, seek, size, func, priv) tb_aico_sendf_(aico, file, seek, size, func, priv __tb_debug_vals__) -#define tb_aico_read(aico, seek, data, size, func, priv) tb_aico_read_(aico, seek, data, size, func, priv __tb_debug_vals__) -#define tb_aico_writ(aico, seek, data, size, func, priv) tb_aico_writ_(aico, seek, data, size, func, priv __tb_debug_vals__) -#define tb_aico_readv(aico, seek, list, size, func, priv) tb_aico_readv_(aico, seek, list, size, func, priv __tb_debug_vals__) -#define tb_aico_writv(aico, seek, list, size, func, priv) tb_aico_writv_(aico, seek, list, size, func, priv __tb_debug_vals__) -#define tb_aico_fsync(aico, func, priv) tb_aico_fsync_(aico, func, priv __tb_debug_vals__) - -#define tb_aico_clos_after(aico, delay, func, priv) tb_aico_clos_after_(aico, delay, func, priv __tb_debug_vals__) -#define tb_aico_acpt_after(aico, delay, func, priv) tb_aico_acpt_after_(aico, delay, func, priv __tb_debug_vals__) -#define tb_aico_conn_after(aico, delay, addr, func, priv) tb_aico_conn_after_(aico, delay, addr, func, priv __tb_debug_vals__) -#define tb_aico_recv_after(aico, delay, data, size, func, priv) tb_aico_recv_after_(aico, delay, data, size, func, priv __tb_debug_vals__) -#define tb_aico_send_after(aico, delay, data, size, func, priv) tb_aico_send_after_(aico, delay, data, size, func, priv __tb_debug_vals__) -#define tb_aico_urecv_after(aico, delay, data, size, func, priv) tb_aico_urecv_after_(aico, delay, data, size, func, priv __tb_debug_vals__) -#define tb_aico_usend_after(aico, delay, addr, data, size, func, priv) tb_aico_usend_after_(aico, delay, addr, data, size, func, priv __tb_debug_vals__) -#define tb_aico_recvv_after(aico, delay, list, size, func, priv) tb_aico_recvv_after_(aico, delay, list, size, func, priv __tb_debug_vals__) -#define tb_aico_sendv_after(aico, delay, list, size, func, priv) tb_aico_sendv_after_(aico, delay, list, size, func, priv __tb_debug_vals__) -#define tb_aico_urecvv_after(aico, delay, addr, list, size, func, priv) tb_aico_urecvv_after_(aico, delay, addr, list, size, func, priv __tb_debug_vals__) -#define tb_aico_usendv_after(aico, delay, addr, list, size, func, priv) tb_aico_usendv_after_(aico, delay, addr, list, size, func, priv __tb_debug_vals__) -#define tb_aico_sendf_after(aico, delay, file, seek, size, func, priv) tb_aico_sendf_after_(aico, delay, file, seek, size, func, priv __tb_debug_vals__) -#define tb_aico_read_after(aico, delay, seek, data, size, func, priv) tb_aico_read_after_(aico, delay, seek, data, size, func, priv __tb_debug_vals__) -#define tb_aico_writ_after(aico, delay, seek, data, size, func, priv) tb_aico_writ_after_(aico, delay, seek, data, size, func, priv __tb_debug_vals__) -#define tb_aico_readv_after(aico, delay, seek, list, size, func, priv) tb_aico_readv_after_(aico, delay, seek, list, size, func, priv __tb_debug_vals__) -#define tb_aico_writv_after(aico, delay, seek, list, size, func, priv) tb_aico_writv_after_(aico, delay, seek, list, size, func, priv __tb_debug_vals__) -#define tb_aico_fsync_after(aico, delay, func, priv) tb_aico_fsync_after_(aico, delay, func, priv __tb_debug_vals__) - -#define tb_aico_task_run(aico, delay, func, priv) tb_aico_task_run_(aico, delay, func, priv __tb_debug_vals__) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -struct __tb_aice_t; -/// the aico func type -typedef tb_bool_t (*tb_aico_func_t)(struct __tb_aice_t* aice); - -/// the aico type enum -typedef enum __tb_aico_type_e -{ - TB_AICO_TYPE_NONE = 0 //!< null -, TB_AICO_TYPE_SOCK = 1 //!< sock -, TB_AICO_TYPE_FILE = 2 //!< file -, TB_AICO_TYPE_TASK = 3 //!< task -, TB_AICO_TYPE_MAXN = 4 - -}tb_aico_type_e; - -/// the aico timeout enum, only for sock -typedef enum __tb_aico_timeout_e -{ - TB_AICO_TIMEOUT_CONN = 0 -, TB_AICO_TIMEOUT_RECV = 1 -, TB_AICO_TIMEOUT_SEND = 2 -, TB_AICO_TIMEOUT_MAXN = 3 - -}tb_aico_timeout_e; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init the aico - * - * @param aicp the aicp - * - * @return the aico - */ -__tb_deprecated__ -tb_aico_ref_t tb_aico_init(tb_aicp_ref_t aicp); - -/*! open the sock aico - * - * @param aicp the aicp - * @param sock the socket - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_open_sock(tb_aico_ref_t aico, tb_socket_ref_t sock); - -/*! open the sock aico from the socket type - * - * @param aicp the aicp - * @param type the socket type - * @param family the address family, default: ipv4 - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_open_sock_from_type(tb_aico_ref_t aico, tb_size_t type, tb_size_t family); - -/*! open the file aico - * - * @param aicp the aicp - * @param file the file - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_open_file(tb_aico_ref_t aico, tb_file_ref_t file); - -/*! open the file aico from path - * - * @param aicp the aicp - * @param path the file path - * @param mode the file mode - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_open_file_from_path(tb_aico_ref_t aico, tb_char_t const* path, tb_size_t mode); - -/*! open the task aico - * - * @param aicp the aicp - * @param ltimer is the lower precision timer? - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_open_task(tb_aico_ref_t aico, tb_bool_t ltimer); - -/*! kill the aico - * - * @param aico the aico - */ -__tb_deprecated__ -tb_void_t tb_aico_kill(tb_aico_ref_t aico); - -/*! exit the aico - * - * @param aico the aico - */ -__tb_deprecated__ -tb_void_t tb_aico_exit(tb_aico_ref_t aico); - -/*! the aico aicp - * - * @param aico the aico - * - * @return the aico aicp - */ -__tb_deprecated__ -tb_aicp_ref_t tb_aico_aicp(tb_aico_ref_t aico); - -/*! the aico type - * - * @param aico the aico - * - * @return the aico type - */ -__tb_deprecated__ -tb_size_t tb_aico_type(tb_aico_ref_t aico); - -/*! get the socket if the aico is socket type - * - * @param aico the aico - * - * @return the socket - */ -__tb_deprecated__ -tb_socket_ref_t tb_aico_sock(tb_aico_ref_t aico); - -/*! get the file if the aico is file type - * - * @param aico the aico - * - * @return the file - */ -__tb_deprecated__ -tb_file_ref_t tb_aico_file(tb_aico_ref_t aico); - -/*! try to close it - * - * @param aico the aico - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_clos_try(tb_aico_ref_t aico); - -/*! the aico timeout - * - * @param aico the aico - * @param type the timeout type - * - * @return the timeout - */ -__tb_deprecated__ -tb_long_t tb_aico_timeout(tb_aico_ref_t aico, tb_size_t type); - -/*! set the aico timeout - * - * @param aico the aico - * @param type the timeout type - * @param timeout the timeout - */ -__tb_deprecated__ -tb_void_t tb_aico_timeout_set(tb_aico_ref_t aico, tb_size_t type, tb_long_t timeout); - -/*! post the clos - * - * @param aicp the aicp - * @param func the func - * @param priv the func private data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_clos_(tb_aico_ref_t aico, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the acpt - * - * @param aico the aico - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_acpt_(tb_aico_ref_t aico, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the conn - * - * @param aico the aico - * @param addr the address - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_conn_(tb_aico_ref_t aico, tb_ipaddr_ref_t addr, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the recv for sock - * - * @param aico the aico - * @param data the data - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_recv_(tb_aico_ref_t aico, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the send for sock - * - * @param aico the aico - * @param data the data - * @param size the size, send the left file data if size == 0 - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_send_(tb_aico_ref_t aico, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the urecv for sock - * - * @param aico the aico - * @param data the data - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_urecv_(tb_aico_ref_t aico, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the usend for sock - * - * @param aico the aico - * @param addr the addr - * @param data the data - * @param size the size, send the left file data if size == 0 - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_usend_(tb_aico_ref_t aico, tb_ipaddr_ref_t addr, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the recvv for sock - * - * @param aico the aico - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_recvv_(tb_aico_ref_t aico, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the sendv for sock - * - * @param aico the aico - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_sendv_(tb_aico_ref_t aico, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the urecvv for sock - * - * @param aico the aico - * @param addr the addr - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_urecvv_(tb_aico_ref_t aico, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the usendv for sock - * - * @param aico the aico - * @param addr the addr - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_usendv_(tb_aico_ref_t aico, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the sendfile for sock - * - * @param aico the aico - * @param file the file handle - * @param seek the seek - * @param size the size, send the left data if size == 0 - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_sendf_(tb_aico_ref_t aico, tb_file_ref_t file, tb_hize_t seek, tb_hize_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the read for file - * - * @param aico the aico - * @param seek the seek - * @param data the data - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_read_(tb_aico_ref_t aico, tb_hize_t seek, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the writ for file - * - * @param aico the aico - * @param seek the seek - * @param data the data - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_writ_(tb_aico_ref_t aico, tb_hize_t seek, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the readv for file - * - * @param aico the aico - * @param seek the seek - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_readv_(tb_aico_ref_t aico, tb_hize_t seek, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the writv for file - * - * @param aico the aico - * @param seek the seek - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_writv_(tb_aico_ref_t aico, tb_hize_t seek, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the fsync for file - * - * @param aico the aico - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_fsync_(tb_aico_ref_t aico, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the clos after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_clos_after_(tb_aico_ref_t aico, tb_size_t delay, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the acpt after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_acpt_after_(tb_aico_ref_t aico, tb_size_t delay, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the conn after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param addr the address - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_conn_after_(tb_aico_ref_t aico, tb_size_t delay, tb_ipaddr_ref_t addr, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the recv for sock after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param data the data - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_recv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the send for sock after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param data the data - * @param size the size, send the left file data if size == 0 - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_send_after_(tb_aico_ref_t aico, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the urecv for sock after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param data the data - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_urecv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the usend for sock after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param addr the addr - * @param data the data - * @param size the size, send the left file data if size == 0 - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_usend_after_(tb_aico_ref_t aico, tb_size_t delay, tb_ipaddr_ref_t addr, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the recvv for sock after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_recvv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the sendv for sock after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_sendv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the urecvv for sock after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param addr the addr - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_urecvv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the usendv for sock after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param addr the addr - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_usendv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_ipaddr_ref_t addr, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the sendfile for sock after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param file the file handle - * @param seek the seek - * @param size the size, send the left data if size == 0 - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_sendf_after_(tb_aico_ref_t aico, tb_size_t delay, tb_file_ref_t file, tb_hize_t seek, tb_hize_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the read for file after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param seek the seek - * @param data the data - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_read_after_(tb_aico_ref_t aico, tb_size_t delay, tb_hize_t seek, tb_byte_t* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the writ for file after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param seek the seek - * @param data the data - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_writ_after_(tb_aico_ref_t aico, tb_size_t delay, tb_hize_t seek, tb_byte_t const* data, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the readv for file after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param seek the seek - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_readv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_hize_t seek, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the writv for file after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param seek the seek - * @param list the list - * @param size the size - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_writv_after_(tb_aico_ref_t aico, tb_size_t delay, tb_hize_t seek, tb_iovec_t const* list, tb_size_t size, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! post the fsync for file after the delay time - * - * @param aico the aico - * @param delay the delay time, ms - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_fsync_after_(tb_aico_ref_t aico, tb_size_t delay, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/*! run aico task after timeout and will be auto-remove it after be expired - * - * only once, need continue to call it again if want to repeat task - * - * @param aico the aico - * @param delay the delay time, ms - * @param func the callback func - * @param priv the callback data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aico_task_run_(tb_aico_ref_t aico, tb_size_t delay, tb_aico_func_t func, tb_cpointer_t priv __tb_debug_decl__); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/aicp.c b/core/src/tbox/src/tbox/asio/deprecated/aicp.c deleted file mode 100644 index d4373391b..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aicp.c +++ /dev/null @@ -1,596 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aicp.c - * @ingroup asio - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "aicp" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "aicp.h" -#include "aico.h" -#include "impl/prefix.h" -#include "../../math/math.h" -#include "../../utils/utils.h" -#include "../../memory/memory.h" -#include "../../platform/platform.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -static tb_bool_t tb_aicp_walk_wait(tb_pointer_t item, tb_cpointer_t priv) -{ - // check - tb_aico_impl_t* aico = (tb_aico_impl_t*)item; - tb_assert_and_check_return_val(aico, tb_false); - - // trace -#ifdef __tb_debug__ - tb_trace_e("aico[%p]: wait exited failed, type: %lu, handle: %p, state: %s for func: %s, line: %lu, file: %s", aico, tb_aico_type((tb_aico_ref_t)aico), aico->handle, tb_state_cstr(tb_atomic_get(&aico->state)), aico->func, aico->line, aico->file); -#else - tb_trace_e("aico[%p]: wait exited failed, type: %lu, handle: %p, state: %s", aico, tb_aico_type((tb_aico_ref_t)aico), aico->handle, tb_state_cstr(tb_atomic_get(&aico->state))); -#endif - - // ok - return tb_true; -} -static tb_bool_t tb_aicp_walk_kill(tb_pointer_t item, tb_cpointer_t priv) -{ - // check - tb_aico_impl_t* aico = (tb_aico_impl_t*)item; - tb_assert_and_check_return_val(aico, tb_false); - - // kill it - tb_aico_kill((tb_aico_ref_t)aico); - - // ok - return tb_true; -} -static tb_bool_t tb_aicp_post_after_func(tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_RUNTASK, tb_false); - - // the posted aice - tb_aice_ref_t posted_aice = (tb_aice_ref_t)aice->priv; - tb_assert_and_check_return_val(posted_aice && posted_aice->aico, tb_false); - - // the impl - tb_aicp_impl_t* impl = (tb_aicp_impl_t*)tb_aico_aicp(aice->aico); - tb_assert_and_check_return_val(impl && impl->ptor && impl->ptor->post, tb_false); - - // ok? - tb_bool_t ok = tb_true; - tb_bool_t posted = tb_true; - if (aice->state == TB_STATE_OK) - { - // post it -#ifdef __tb_debug__ - if (!tb_aicp_post_((tb_aicp_ref_t)impl, posted_aice, ((tb_aico_impl_t*)aice->aico)->func, ((tb_aico_impl_t*)aice->aico)->line, ((tb_aico_impl_t*)aice->aico)->file)) -#else - if (!tb_aicp_post_((tb_aicp_ref_t)impl, posted_aice)) -#endif - { - // not posted - posted = tb_false; - - // failed - posted_aice->state = TB_STATE_FAILED; - } - } - // failed? - else - { - // not posted - posted = tb_false; - - // save state - posted_aice->state = aice->state; - } - - // not posted? done func now - if (!posted) - { - // done func: notify failed - if (posted_aice->func && !posted_aice->func(posted_aice)) ok = tb_false; - } - - // exit the posted aice - tb_free(posted_aice); - - // ok? - return ok; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * instance implementation - */ -static tb_int_t tb_aicp_instance_loop(tb_cpointer_t priv) -{ - // aicp - tb_aicp_ref_t aicp = (tb_aicp_ref_t)priv; - - // trace - tb_trace_d("loop: init"); - - // loop aicp - if (aicp) tb_aicp_loop(aicp); - - // trace - tb_trace_d("loop: exit"); - - // exit - return 0; -} -static tb_handle_t tb_aicp_instance_init(tb_cpointer_t* ppriv) -{ - // check - tb_assert_and_check_return_val(ppriv, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_aicp_ref_t aicp = tb_null; - do - { - // init aicp - aicp = tb_aicp_init(0); - tb_assert_and_check_break(aicp); - - // init loop - *ppriv = (tb_cpointer_t)tb_thread_init(tb_null, tb_aicp_instance_loop, aicp, 0); - tb_assert_and_check_break(*ppriv); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit aicp - if (aicp) tb_aicp_exit(aicp); - aicp = tb_null; - } - - // ok? - return (tb_handle_t)aicp; -} -static tb_void_t tb_aicp_instance_exit(tb_handle_t handle, tb_cpointer_t priv) -{ - // check - tb_assert_and_check_return(handle); - - // wait all - if (!tb_aicp_wait_all((tb_aicp_ref_t)handle, 5000)) return ; - - // kill aicp - tb_aicp_kill((tb_aicp_ref_t)handle); - - // exit loop - tb_thread_ref_t loop = (tb_thread_ref_t)priv; - if (loop) - { - // wait it - if (!tb_thread_wait(loop, 5000, tb_null)) return ; - - // exit it - tb_thread_exit(loop); - } - - // exit it - tb_aicp_exit((tb_aicp_ref_t)handle); -} -static tb_void_t tb_aicp_instance_kill(tb_handle_t handle, tb_cpointer_t priv) -{ - // check - tb_assert_and_check_return(handle); - - // kill all - tb_aicp_kill_all((tb_aicp_ref_t)handle); -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_aicp_ref_t tb_aicp() -{ - return (tb_aicp_ref_t)tb_singleton_instance(TB_SINGLETON_TYPE_AICP, tb_aicp_instance_init, tb_aicp_instance_exit, tb_aicp_instance_kill, tb_null); -} -tb_aicp_ref_t tb_aicp_init(tb_size_t maxn) -{ - // check iovec - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, data, tb_iovec_t, data), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, size, tb_iovec_t, size), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_send_t, data, tb_iovec_t, data), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_send_t, size, tb_iovec_t, size), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_read_t, data, tb_iovec_t, data), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_read_t, size, tb_iovec_t, size), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_writ_t, data, tb_iovec_t, data), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_writ_t, size, tb_iovec_t, size), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_urecv_t, data, tb_iovec_t, data), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_urecv_t, size, tb_iovec_t, size), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_usend_t, data, tb_iovec_t, data), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_usend_t, size, tb_iovec_t, size), tb_null); - - // check real - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_send_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_read_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_writ_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_sendf_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_sendv_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_recvv_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_readv_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_writv_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_urecv_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_usend_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_urecvv_t, real), tb_null); - tb_assert_and_check_return_val(tb_memberof_eq(tb_aice_recv_t, real, tb_aice_usendv_t, real), tb_null); - - // done - tb_bool_t ok = tb_false; - tb_aicp_impl_t* impl = tb_null; - do - { - // make impl - impl = tb_malloc0_type(tb_aicp_impl_t); - tb_assert_and_check_break(impl); - - // init impl -#ifdef __tb_small__ - impl->maxn = maxn? maxn : (1 << 4); -#else - impl->maxn = maxn? maxn : (1 << 8); -#endif - - // init lock - if (!tb_spinlock_init(&impl->lock)) break; - - // init proactor - impl->ptor = tb_aicp_ptor_impl_init(impl); - tb_assert_and_check_break(impl->ptor && impl->ptor->step >= sizeof(tb_aico_impl_t)); - - // init aico pool - impl->pool = tb_fixed_pool_init(tb_null, (impl->maxn >> 4) + 16, impl->ptor->step, tb_null, tb_null, tb_null); - tb_assert_and_check_break(impl->pool); - - // register lock profiler -#ifdef TB_LOCK_PROFILER_ENABLE - tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&impl->lock, TB_TRACE_MODULE_NAME); -#endif - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit impl - if (impl) tb_aicp_exit((tb_aicp_ref_t)impl); - impl = tb_null; - } - - // ok? - return (tb_aicp_ref_t)impl; -} -tb_bool_t tb_aicp_exit(tb_aicp_ref_t aicp) -{ - // check - tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; - tb_assert_and_check_return_val(impl, tb_false); - - // kill all first - tb_aicp_kill_all((tb_aicp_ref_t)impl); - - // wait all exiting - if (tb_aicp_wait_all((tb_aicp_ref_t)impl, 5000) <= 0) - { - // wait failed, trace left aicos - tb_spinlock_enter(&impl->lock); - if (impl->pool) tb_fixed_pool_walk(impl->pool, tb_aicp_walk_wait, tb_null); - tb_spinlock_leave(&impl->lock); - return tb_false; - } - - // kill loop - tb_aicp_kill((tb_aicp_ref_t)impl); - - // wait workers exiting - tb_hong_t time = tb_mclock(); - while (tb_atomic_get(&impl->work) && (tb_mclock() < time + 5000)) tb_msleep(500); - - // exit proactor - if (impl->ptor) - { - tb_assert(impl->ptor && impl->ptor->exit); - impl->ptor->exit(impl->ptor); - impl->ptor = tb_null; - } - - // exit aico pool - tb_spinlock_enter(&impl->lock); - if (impl->pool) tb_fixed_pool_exit(impl->pool); - impl->pool = tb_null; - tb_spinlock_leave(&impl->lock); - - // exit lock - tb_spinlock_exit(&impl->lock); - - // free impl - tb_free(impl); - - // ok - return tb_true; -} -tb_size_t tb_aicp_maxn(tb_aicp_ref_t aicp) -{ - // check - tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; - tb_assert_and_check_return_val(impl, 0); - - // the maxn - return impl->maxn; -} -tb_bool_t tb_aicp_post_(tb_aicp_ref_t aicp, tb_aice_ref_t aice __tb_debug_decl__) -{ - // check - tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; - tb_assert_and_check_return_val(impl && impl->ptor && impl->ptor->post, tb_false); - tb_assert_and_check_return_val(aice && aice->aico, tb_false); - - // the aico - tb_aico_impl_t* aico = (tb_aico_impl_t*)aice->aico; - tb_assert_and_check_return_val(aico, tb_false); - - // opened or killed or closed? pending it - tb_size_t state = tb_atomic_fetch_and_pset(&aico->state, TB_STATE_OPENED, TB_STATE_PENDING); - if (state == TB_STATE_OPENED || state == TB_STATE_KILLED) - { - // save debug info -#ifdef __tb_debug__ - aico->func = func_; - aico->file = file_; - aico->line = line_; -#endif - - // post aice - return impl->ptor->post(impl->ptor, aice); - } - - // trace -#ifdef __tb_debug__ - tb_trace_e("post aice[%lu] failed, the aico[%p]: type: %lu, handle: %p, state: %s for func: %s, line: %lu, file: %s", aice->code, aico, tb_aico_type((tb_aico_ref_t)aico), aico->handle, tb_state_cstr(state), func_, line_, file_); -#else - tb_trace_e("post aice[%lu] failed, the aico[%p]: type: %lu, handle: %p, state: %s", aice->code, aico, tb_aico_type((tb_aico_ref_t)aico), aico->handle, tb_state_cstr(state)); -#endif - - // abort it - tb_assert(0); - - // post failed - return tb_false; -} -tb_bool_t tb_aicp_post_after_(tb_aicp_ref_t aicp, tb_size_t delay, tb_aice_ref_t aice __tb_debug_decl__) -{ - // check - tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; - tb_assert_and_check_return_val(impl && impl->ptor && impl->ptor->post, tb_false); - tb_assert_and_check_return_val(aice && aice->aico, tb_false); - - // killed? - tb_check_return_val(!tb_atomic_get(&impl->kill_all), tb_false); - - // no delay? - if (!delay) return tb_aicp_post_(aicp, aice __tb_debug_args__); - - // the aico - tb_aico_impl_t* aico = (tb_aico_impl_t*)aice->aico; - tb_assert_and_check_return_val(aico, tb_false); - - // make the posted aice - tb_aice_ref_t posted_aice = tb_malloc0_type(tb_aice_t); - tb_assert_and_check_return_val(posted_aice, tb_false); - - // init the posted aice - *posted_aice = *aice; - - // run the delay task - return tb_aico_task_run_((tb_aico_ref_t)aico, delay, tb_aicp_post_after_func, posted_aice __tb_debug_args__); -} -tb_void_t tb_aicp_loop(tb_aicp_ref_t aicp) -{ - tb_aicp_loop_util(aicp, tb_null, tb_null); -} -tb_void_t tb_aicp_loop_util(tb_aicp_ref_t aicp, tb_bool_t (*stop)(tb_cpointer_t priv), tb_cpointer_t priv) -{ - // check - tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; - tb_assert_and_check_return(impl); - - // the ptor - tb_aicp_ptor_impl_t* ptor = impl->ptor; - tb_assert_and_check_return(ptor && ptor->loop_spak); - - // the loop spak - tb_long_t (*loop_spak)(tb_aicp_ptor_impl_t* , tb_handle_t, tb_aice_ref_t , tb_long_t ) = ptor->loop_spak; - - // worker++ - tb_atomic_fetch_and_inc(&impl->work); - - // init loop - tb_handle_t loop = ptor->loop_init? ptor->loop_init(ptor) : tb_null; - - // trace - tb_trace_d("loop[%p]: init", loop); - - // spak ctime - tb_cache_time_spak(); - - // loop - while (1) - { - // spak - tb_aice_t resp = {0}; - tb_long_t ok = loop_spak(ptor, loop, &resp, -1); - - // spak ctime - tb_cache_time_spak(); - - // failed? - tb_check_break(ok >= 0); - - // timeout? - tb_check_continue(ok); - - // check aico - tb_aico_impl_t* aico = (tb_aico_impl_t*)resp.aico; - tb_assert_and_check_continue(aico); - - // trace - tb_trace_d("loop[%p]: spak: code: %lu, aico: %p, state: %s: %ld", loop, resp.code, aico, aico? tb_state_cstr(tb_atomic_get(&aico->state)) : "null", ok); - - // pending? clear state if be not accept or accept failed - tb_size_t state = TB_STATE_OPENED; - state = (resp.code != TB_AICE_CODE_ACPT || resp.state != TB_STATE_OK)? tb_atomic_fetch_and_pset(&aico->state, TB_STATE_PENDING, state) : tb_atomic_get(&aico->state); - - // killed or killing? - if (state == TB_STATE_KILLED || state == TB_STATE_KILLING) - { - // update the aice state - resp.state = TB_STATE_KILLED; - - // killing? update to the killed state - tb_atomic_fetch_and_pset(&aico->state, TB_STATE_KILLING, TB_STATE_KILLED); - } - - // done func, @note maybe the aico exit will be called - if (resp.func && !resp.func(&resp)) - { - // trace -#ifdef __tb_debug__ - tb_trace_e("loop[%p]: done aice func failed with code: %lu at line: %lu, func: %s, file: %s!", loop, resp.code, aico->line, aico->func, aico->file); -#else - tb_trace_e("loop[%p]: done aice func failed with code: %lu!", loop, resp.code); -#endif - } - - // killing? update to the killed state - tb_atomic_fetch_and_pset(&aico->state, TB_STATE_KILLING, TB_STATE_KILLED); - - // stop it? - if (stop && stop(priv)) tb_aicp_kill(aicp); - } - - // exit loop - if (ptor->loop_exit) ptor->loop_exit(ptor, loop); - - // worker-- - tb_atomic_fetch_and_dec(&impl->work); - - // trace - tb_trace_d("loop[%p]: exit", loop); -} -tb_void_t tb_aicp_kill(tb_aicp_ref_t aicp) -{ - // check - tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; - tb_assert_and_check_return(impl); - - // trace - tb_trace_d("kill: .."); - - // kill all - tb_aicp_kill_all(aicp); - - // kill it - if (!tb_atomic_fetch_and_set(&impl->kill, 1)) - { - // kill proactor - if (impl->ptor && impl->ptor->kill) impl->ptor->kill(impl->ptor); - } -} -tb_void_t tb_aicp_kill_all(tb_aicp_ref_t aicp) -{ - // check - tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; - tb_assert_and_check_return(impl); - - // trace - tb_trace_d("kill: all: .."); - - // kill all - if (!tb_atomic_fetch_and_set(&impl->kill_all, 1)) - { - tb_spinlock_enter(&impl->lock); - if (impl->pool) tb_fixed_pool_walk(impl->pool, tb_aicp_walk_kill, impl); - tb_spinlock_leave(&impl->lock); - } -} -tb_long_t tb_aicp_wait_all(tb_aicp_ref_t aicp, tb_long_t timeout) -{ - // check - tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; - tb_assert_and_check_return_val(impl, -1); - - // trace - tb_trace_d("wait: all: .."); - - // wait it - tb_size_t size = 0; - tb_hong_t time = tb_cache_time_spak(); - while ((timeout < 0 || tb_cache_time_spak() < time + timeout)) - { - // enter - tb_spinlock_enter(&impl->lock); - - // the aico count - size = impl->pool? tb_fixed_pool_size(impl->pool) : 0; - - // trace - tb_trace_d("wait: count: %lu: ..", size); - - // leave - tb_spinlock_leave(&impl->lock); - - // ok? - tb_check_break(size); - - // wait some time - tb_msleep(200); - } - - // ok? - return !size? 1 : 0; -} -tb_hong_t tb_aicp_time(tb_aicp_ref_t aicp) -{ - return tb_cache_time_mclock(); -} diff --git a/core/src/tbox/src/tbox/asio/deprecated/aicp.h b/core/src/tbox/src/tbox/asio/deprecated/aicp.h deleted file mode 100644 index a3e302952..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aicp.h +++ /dev/null @@ -1,180 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aicp.h - * @ingroup asio - * - */ -#ifndef TB_ASIO_AICP_H -#define TB_ASIO_AICP_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "aice.h" -#include "../../platform/timer.h" -#include "../../container/container.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -/// post -#define tb_aicp_post(aicp, aice) tb_aicp_post_(aicp, aice __tb_debug_vals__) -#define tb_aicp_post_after(aicp, delay, aice) tb_aicp_post_after_(aicp, delay, aice __tb_debug_vals__) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the aicp instance - * - * @return the aicp - */ -__tb_deprecated__ -tb_aicp_ref_t tb_aicp(tb_noarg_t); - -/*! init the aicp - * - * @param maxn the aico maxn, using the default maxn if be zero - * - * @return the aicp - */ -__tb_deprecated__ -tb_aicp_ref_t tb_aicp_init(tb_size_t maxn); - -/*! exit the aicp - * - * @param aicp the aicp - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_exit(tb_aicp_ref_t aicp); - -/*! the aico maxn - * - * @param aicp the aicp - * - * @return the aico maxn - */ -__tb_deprecated__ -tb_size_t tb_aicp_maxn(tb_aicp_ref_t aicp); - -/*! post the aice - * - * @param aicp the aicp - * @param aice the aice - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_post_(tb_aicp_ref_t aicp, tb_aice_ref_t aice __tb_debug_decl__); - -/*! post the aice - * - * @param aicp the aicp - * @param delay the delay time, ms - * @param aice the aice - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_post_after_(tb_aicp_ref_t aicp, tb_size_t delay, tb_aice_ref_t aice __tb_debug_decl__); - -/*! loop aicp for the external thread - * - * @code - * tb_pointer_t tb_aicp_worker_thread(tb_pointer_t) - * { - * tb_aicp_loop(aicp); - * } - * @endcode - * - * @param aicp the aicp - */ -__tb_deprecated__ -tb_void_t tb_aicp_loop(tb_aicp_ref_t aicp); - -/*! loop aicp util ... for the external thread - * - * @code - * tb_bool_t tb_aicp_stop_func(tb_pointer_t) - * { - * if (...) return tb_true; - * return tb_false; - * } - * tb_pointer_t tb_aicp_worker_thread(tb_pointer_t) - * { - * tb_aicp_loop_util(aicp, stop_func, tb_null); - * } - * @endcode - * - * @param aicp the aicp - */ -__tb_deprecated__ -tb_void_t tb_aicp_loop_util(tb_aicp_ref_t aicp, tb_bool_t (*stop)(tb_cpointer_t priv), tb_cpointer_t priv); - -/*! kill loop - * - * @param aicp the aicp - */ -__tb_deprecated__ -tb_void_t tb_aicp_kill(tb_aicp_ref_t aicp); - -/*! kill all and cannot continue to post it, but not kill loop - * - * @param aicp the aicp - */ -__tb_deprecated__ -tb_void_t tb_aicp_kill_all(tb_aicp_ref_t aicp); - -/*! wait all exiting - * - * @param aicp the aicp - * @param timeout the timeout - * - * @return ok: > 0, timeout: 0, failed: -1 - */ -__tb_deprecated__ -tb_long_t tb_aicp_wait_all(tb_aicp_ref_t aicp, tb_long_t timeout); - -/*! the spak time - * - * @param aicp the aicp - * - * @return the time - */ -__tb_deprecated__ -tb_hong_t tb_aicp_time(tb_aicp_ref_t aicp); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/aioe.h b/core/src/tbox/src/tbox/asio/deprecated/aioe.h deleted file mode 100644 index 7bc84c34e..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aioe.h +++ /dev/null @@ -1,76 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aioe.h - * @ingroup asio - * - */ -#ifndef TB_ASIO_AIOE_H -#define TB_ASIO_AIOE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the aioe code enum, only for sock -typedef enum __tb_aioe_code_e -{ - TB_AIOE_CODE_NONE = 0x0000 -, TB_AIOE_CODE_CONN = 0x0001 -, TB_AIOE_CODE_ACPT = 0x0002 -, TB_AIOE_CODE_RECV = 0x0004 -, TB_AIOE_CODE_SEND = 0x0008 -, TB_AIOE_CODE_EALL = TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND | TB_AIOE_CODE_ACPT | TB_AIOE_CODE_CONN -, TB_AIOE_CODE_CLEAR = 0x0010 //!< edge trigger. after the event is retrieved by the user, its state is reset -, TB_AIOE_CODE_ONESHOT = 0x0020 //!< causes the event to return only the first occurrence of the filter being triggered - -}tb_aioe_code_e; - -/// the aioe type -typedef struct __tb_aioe_t -{ - /// the code - tb_size_t code; - - /// the priv - tb_cpointer_t priv; - - /// the aioo - tb_aioo_ref_t aioo; - -}tb_aioe_t, *tb_aioe_ref_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/aioo.c b/core/src/tbox/src/tbox/asio/deprecated/aioo.c deleted file mode 100644 index 696e20a2f..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aioo.c +++ /dev/null @@ -1,59 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aioo.c - * @ingroup asio - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "aioo.h" -#include "aioe.h" -#include "impl/prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * declaration - */ -tb_long_t tb_aioo_rtor_wait(tb_socket_ref_t sock, tb_size_t code, tb_long_t timeout); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_socket_ref_t tb_aioo_sock(tb_aioo_ref_t aioo) -{ - // check - tb_aioo_impl_t const* impl = (tb_aioo_impl_t const*)aioo; - tb_assert_and_check_return_val(impl, tb_null); - - // the sock - return impl->sock; -} -tb_long_t tb_aioo_wait(tb_socket_ref_t sock, tb_size_t code, tb_long_t timeout) -{ - // check - tb_assert_and_check_return_val(sock && code, 0); - - // wait aioo - return tb_aioo_rtor_wait(sock, code, timeout); -} - diff --git a/core/src/tbox/src/tbox/asio/deprecated/aioo.h b/core/src/tbox/src/tbox/asio/deprecated/aioo.h deleted file mode 100644 index f6c8bc7ed..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aioo.h +++ /dev/null @@ -1,72 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aioo.h - * @ingroup asio - * - */ -#ifndef TB_ASIO_AIOO_H -#define TB_ASIO_AIOO_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the aioo handle - * - * @param aioo the aioo - * - * @return the socket - */ -__tb_deprecated__ -tb_socket_ref_t tb_aioo_sock(tb_aioo_ref_t aioo); - -/*! wait the aioo - * - * blocking wait the single event aioo, so need not aiop - * return the event type if ok, otherwise return 0 for timeout - * - * @param sock the sock - * @param code the aioe code - * @param timeout the timeout, infinity: -1 - * - * @return > 0: the aioe code, 0: timeout, -1: failed - */ -__tb_deprecated__ -tb_long_t tb_aioo_wait(tb_socket_ref_t sock, tb_size_t code, tb_long_t timeout); - - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/aiop.c b/core/src/tbox/src/tbox/asio/deprecated/aiop.c deleted file mode 100644 index 97d38883a..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aiop.c +++ /dev/null @@ -1,326 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aiop.c - * @ingroup asio - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "aiop" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "aiop.h" -#include "aioo.h" -#include "impl/prefix.h" -#include "../../math/math.h" -#include "../../utils/utils.h" -#include "../../memory/memory.h" -#include "../../platform/platform.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * aioo - */ -static tb_aioo_ref_t tb_aiop_aioo_init(tb_aiop_impl_t* impl, tb_socket_ref_t sock, tb_size_t code, tb_cpointer_t priv) -{ - // check - tb_assert_and_check_return_val(impl && impl->pool, tb_null); - - // enter - tb_spinlock_enter(&impl->lock); - - // make aioo - tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)tb_fixed_pool_malloc0(impl->pool); - - // init aioo - if (aioo) - { - aioo->code = code; - aioo->priv = priv; - aioo->sock = sock; - } - - // leave - tb_spinlock_leave(&impl->lock); - - // ok? - return (tb_aioo_ref_t)aioo; -} -static tb_void_t tb_aiop_aioo_exit(tb_aiop_impl_t* impl, tb_aioo_ref_t aioo) -{ - // check - tb_assert_and_check_return(impl && impl->pool); - - // enter - tb_spinlock_enter(&impl->lock); - - // exit aioo - if (aioo) tb_fixed_pool_free(impl->pool, aioo); - - // leave - tb_spinlock_leave(&impl->lock); -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_aiop_ref_t tb_aiop_init(tb_size_t maxn) -{ - // check - tb_assert_and_check_return_val(maxn, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_aiop_impl_t* impl = tb_null; - do - { - // make impl - impl = tb_malloc0_type(tb_aiop_impl_t); - tb_assert_and_check_break(impl); - - // init impl - impl->maxn = maxn; - - // init lock - if (!tb_spinlock_init(&impl->lock)) break; - - // init pool - impl->pool = tb_fixed_pool_init(tb_null, (maxn >> 4) + 16, sizeof(tb_aioo_impl_t), tb_null, tb_null, tb_null); - tb_assert_and_check_break(impl->pool); - - // init spak - if (!tb_socket_pair(TB_SOCKET_TYPE_TCP, impl->spak)) break; - - // init reactor - impl->rtor = tb_aiop_rtor_impl_init(impl); - tb_assert_and_check_break(impl->rtor); - - // addo spak - if (!tb_aiop_addo((tb_aiop_ref_t)impl, impl->spak[1], TB_AIOE_CODE_RECV, tb_null)) break; - - // register lock profiler -#ifdef TB_LOCK_PROFILER_ENABLE - tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&impl->lock, TB_TRACE_MODULE_NAME); -#endif - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (impl) tb_aiop_exit((tb_aiop_ref_t)impl); - impl = tb_null; - } - - // ok? - return (tb_aiop_ref_t)impl; -} -tb_void_t tb_aiop_exit(tb_aiop_ref_t aiop) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return(impl); - - // exit reactor - if (impl->rtor && impl->rtor->exit) - impl->rtor->exit(impl->rtor); - - // exit spak - if (impl->spak[0]) tb_socket_exit(impl->spak[0]); - if (impl->spak[1]) tb_socket_exit(impl->spak[1]); - impl->spak[0] = tb_null; - impl->spak[1] = tb_null; - - // exit pool - tb_spinlock_enter(&impl->lock); - if (impl->pool) tb_fixed_pool_exit(impl->pool); - impl->pool = tb_null; - tb_spinlock_leave(&impl->lock); - - // exit lock - tb_spinlock_exit(&impl->lock); - - // free impl - tb_free(impl); -} -tb_void_t tb_aiop_cler(tb_aiop_ref_t aiop) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return(impl); - - // clear reactor - if (impl->rtor && impl->rtor->cler) - impl->rtor->cler(impl->rtor); - - // clear pool - tb_spinlock_enter(&impl->lock); - if (impl->pool) tb_fixed_pool_clear(impl->pool); - tb_spinlock_leave(&impl->lock); - - // addo spak - if (impl->spak[1]) tb_aiop_addo(aiop, impl->spak[1], TB_AIOE_CODE_RECV, tb_null); -} -tb_bool_t tb_aiop_have(tb_aiop_ref_t aiop, tb_size_t code) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return_val(impl && impl->rtor, tb_false); - - // have this code? - return ((impl->rtor->code & code) == code)? tb_true : tb_false; -} -tb_void_t tb_aiop_kill(tb_aiop_ref_t aiop) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return(impl); - - // kill it - if (impl->spak[0]) - { - // post: 'k' - tb_long_t ok = tb_socket_send(impl->spak[0], (tb_byte_t const*)"k", 1); - if (ok != 1) - { - // trace - tb_trace_e("kill: failed!"); - - // abort it - tb_assert(0); - } - } -} -tb_void_t tb_aiop_spak(tb_aiop_ref_t aiop) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return(impl); - - // spak it - if (impl->spak[0]) - { - // post: 'p' - tb_long_t ok = tb_socket_send(impl->spak[0], (tb_byte_t const*)"p", 1); - if (ok != 1) - { - // trace - tb_trace_e("spak: failed!"); - - // abort it - tb_assert(0); - } - } -} -tb_aioo_ref_t tb_aiop_addo(tb_aiop_ref_t aiop, tb_socket_ref_t sock, tb_size_t code, tb_cpointer_t priv) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return_val(impl && impl->rtor && impl->rtor->addo && sock, tb_null); - tb_assert(tb_aiop_have(aiop, code)); - - // done - tb_bool_t ok = tb_false; - tb_aioo_ref_t aioo = tb_null; - do - { - // init aioo - aioo = tb_aiop_aioo_init(impl, sock, code, priv); - tb_assert_and_check_break(aioo); - - // addo aioo - if (!impl->rtor->addo(impl->rtor, (tb_aioo_impl_t*)aioo)) break; - - // ok - ok = tb_true; - - } while (0); - - // failed? remove aioo - if (!ok && aioo) - { - tb_aiop_aioo_exit(impl, aioo); - aioo = tb_null; - } - - // ok? - return aioo; -} -tb_void_t tb_aiop_delo(tb_aiop_ref_t aiop, tb_aioo_ref_t aioo) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return(impl && impl->rtor && impl->rtor->delo && aioo); - - // delete aioo from aiop - if (!impl->rtor->delo(impl->rtor, (tb_aioo_impl_t*)aioo)) - { - // trace - tb_trace_e("delo: aioo[%p] failed!", aioo); - } - - // exit aioo - tb_aiop_aioo_exit(impl, aioo); -} -tb_bool_t tb_aiop_post(tb_aiop_ref_t aiop, tb_aioe_ref_t aioe) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return_val(impl && impl->rtor && impl->rtor->post && aioe, tb_false); - tb_assert(tb_aiop_have(aiop, aioe->code)); - - // post - return impl->rtor->post(impl->rtor, aioe); -} -tb_bool_t tb_aiop_sete(tb_aiop_ref_t aiop, tb_aioo_ref_t aioo, tb_size_t code, tb_cpointer_t priv) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return_val(impl && aioo && tb_aioo_sock(aioo) && code, tb_false); - - // init aioe - tb_aioe_t aioe; - aioe.code = code; - aioe.priv = priv; - aioe.aioo = aioo; - - // post aioe - return tb_aiop_post(aiop, &aioe); -} -tb_long_t tb_aiop_wait(tb_aiop_ref_t aiop, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout) -{ - // check - tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; - tb_assert_and_check_return_val(impl && impl->rtor && impl->rtor->wait && list, -1); - - // wait - return impl->rtor->wait(impl->rtor, list, maxn, timeout); -} - diff --git a/core/src/tbox/src/tbox/asio/deprecated/aiop.h b/core/src/tbox/src/tbox/asio/deprecated/aiop.h deleted file mode 100644 index 5a9181f59..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/aiop.h +++ /dev/null @@ -1,156 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aiop.h - * @ingroup asio - * - */ -#ifndef TB_ASIO_AIOP_H -#define TB_ASIO_AIOP_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "aioo.h" -#include "aioe.h" -#include "../../platform/prefix.h" -#include "../../container/container.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init the aiop - * - * @param maxn the maximum number of concurrent objects - * - * @return the aiop - */ -__tb_deprecated__ -tb_aiop_ref_t tb_aiop_init(tb_size_t maxn); - -/*! exit the aiop - * - * @param aiop the aiop - */ -__tb_deprecated__ -tb_void_t tb_aiop_exit(tb_aiop_ref_t aiop); - -/*! cler the aiop - * - * @param aiop the aiop - */ -__tb_deprecated__ -tb_void_t tb_aiop_cler(tb_aiop_ref_t aiop); - -/*! kill the aiop - * - * @param aiop the aiop - */ -__tb_deprecated__ -tb_void_t tb_aiop_kill(tb_aiop_ref_t aiop); - -/*! spak the aiop, break the wait - * - * @param aiop the aiop - */ -__tb_deprecated__ -tb_void_t tb_aiop_spak(tb_aiop_ref_t aiop); - -/*! the aioe code is supported for the aiop? - * - * @param aiop the aiop - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aiop_have(tb_aiop_ref_t aiop, tb_size_t code); - -/*! addo the aioo - * - * @param aiop the aiop - * @param sock the socket - * @param code the code - * @param priv the private data - * - * @return the aioo - */ -__tb_deprecated__ -tb_aioo_ref_t tb_aiop_addo(tb_aiop_ref_t aiop, tb_socket_ref_t sock, tb_size_t code, tb_cpointer_t priv); - -/*! delo the aioo - * - * @param aiop the aiop - * @param aioo the aioo - * - */ -__tb_deprecated__ -tb_void_t tb_aiop_delo(tb_aiop_ref_t aiop, tb_aioo_ref_t aioo); - -/*! post the aioe - * - * @param aiop the aiop - * @param aioe the aioe - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aiop_post(tb_aiop_ref_t aiop, tb_aioe_ref_t aioe); - -/*! set the aioe - * - * @param aiop the aiop - * @param aioo the aioo - * @param code the code - * @param priv the private data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aiop_sete(tb_aiop_ref_t aiop, tb_aioo_ref_t aioo, tb_size_t code, tb_cpointer_t priv); - -/*! wait the asio objects in the pool - * - * blocking wait the multiple event objects - * return the event number if ok, otherwise return 0 for timeout - * - * @param aiop the aiop - * @param list the aioe list - * @param maxn the aioe maxn - * @param timeout the timeout, infinity: -1 - * - * @return > 0: the aioe list size, 0: timeout, -1: failed - */ -__tb_deprecated__ -tb_long_t tb_aiop_wait(tb_aiop_ref_t aiop, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/asio.h b/core/src/tbox/src/tbox/asio/deprecated/asio.h deleted file mode 100644 index a8b872fb0..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/asio.h +++ /dev/null @@ -1,44 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file asio.h - * @defgroup asio - * - */ -#ifndef TB_ASIO_DEPRECATED_H -#define TB_ASIO_DEPRECATED_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "aioo.h" -#include "aioe.h" -#include "aiop.h" -#include "aico.h" -#include "aice.h" -#include "aicp.h" -#include "http.h" -#include "dns.h" -#include "ssl.h" - - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/deprecated.h b/core/src/tbox/src/tbox/asio/deprecated/deprecated.h deleted file mode 100644 index 429191ba8..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/deprecated.h +++ /dev/null @@ -1,35 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file deprecated.h - * @defgroup asio - * - */ -#ifndef TB_ASIO_DEPRECATED_H -#define TB_ASIO_DEPRECATED_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "asio.h" - - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/dns.c b/core/src/tbox/src/tbox/asio/deprecated/dns.c deleted file mode 100644 index 3af9ca589..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/dns.c +++ /dev/null @@ -1,571 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file dns.c - * @ingroup asio - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "aicp_dns" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "dns.h" -#include "aico.h" -#include "aicp.h" -#include "../../network/network.h" -#include "../../platform/platform.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the aicp impl done type -typedef struct __tb_aicp_dns_done_t -{ - // the func - tb_aicp_dns_done_func_t func; - - // the priv - tb_cpointer_t priv; - -}tb_aicp_dns_done_t; - -// the aicp impl type -typedef struct __tb_aicp_dns_impl_t -{ - // the done - tb_aicp_dns_done_t done; - - // the aicp - tb_aicp_ref_t aicp; - - // the aico - tb_aico_ref_t aico; - - // the server indx - tb_size_t indx; - - // the server list - tb_ipaddr_t list[3]; - - // the server size - tb_size_t size; - - // the data - tb_byte_t data[TB_DNS_RPKT_MAXN]; - - // the host - tb_char_t host[256]; - -}tb_aicp_dns_impl_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -static tb_size_t tb_aicp_dns_reqt_init(tb_aicp_dns_impl_t* impl) -{ - // check - tb_assert_and_check_return_val(impl, 0); - - // init query data - tb_static_stream_t stream; - tb_static_stream_init(&stream, impl->data, TB_DNS_RPKT_MAXN); - - // identification number - tb_static_stream_writ_u16_be(&stream, TB_DNS_HEADER_MAGIC); - - /* 0x2104: 0 0000 001 0000 0000 - * - * tb_uint16_t qr :1; // query/response flag - * tb_uint16_t opcode :4; // purpose of message - * tb_uint16_t aa :1; // authoritive answer - * tb_uint16_t tc :1; // truncated message - * tb_uint16_t rd :1; // recursion desired - - * tb_uint16_t ra :1; // recursion available - * tb_uint16_t z :1; // its z! reserved - * tb_uint16_t ad :1; // authenticated data - * tb_uint16_t cd :1; // checking disabled - * tb_uint16_t rcode :4; // response code - * - * this is a query - * this is a standard query - * not authoritive answer - * not truncated - * recursion desired - * - * recursion not available! hey we dont have it (lol) - * - */ -#if 1 - tb_static_stream_writ_u16_be(&stream, 0x0100); -#else - tb_static_stream_writ_u1(&stream, 0); // this is a query - tb_static_stream_writ_ubits32(&stream, 0, 4); // this is a standard query - tb_static_stream_writ_u1(&stream, 0); // not authoritive answer - tb_static_stream_writ_u1(&stream, 0); // not truncated - tb_static_stream_writ_u1(&stream, 1); // recursion desired - - tb_static_stream_writ_u1(&stream, 0); // recursion not available! hey we dont have it (lol) - tb_static_stream_writ_u1(&stream, 0); - tb_static_stream_writ_u1(&stream, 0); - tb_static_stream_writ_u1(&stream, 0); - tb_static_stream_writ_ubits32(&stream, 0, 4); -#endif - - /* we have only one question - * - * tb_uint16_t question; // number of question entries - * tb_uint16_t answer; // number of answer entries - * tb_uint16_t authority; // number of authority entries - * tb_uint16_t resource; // number of resource entries - * - */ - tb_static_stream_writ_u16_be(&stream, 1); - tb_static_stream_writ_u16_be(&stream, 0); - tb_static_stream_writ_u16_be(&stream, 0); - tb_static_stream_writ_u16_be(&stream, 0); - - // set questions, see as tb_dns_question_t - // name + question1 + question2 + ... - tb_static_stream_writ_u8(&stream, '.'); - tb_char_t* p = tb_static_stream_writ_cstr(&stream, impl->host); - - // only one question now. - tb_static_stream_writ_u16_be(&stream, 1); // we are requesting the ipv4 dnsess - tb_static_stream_writ_u16_be(&stream, 1); // it's internet (lol) - - // encode impl name - if (!p || !tb_dns_encode_name(p - 1)) return 0; - - // ok? - return tb_static_stream_offset(&stream); -} -static tb_bool_t tb_aicp_dns_resp_done(tb_aicp_dns_impl_t* impl, tb_size_t size, tb_ipaddr_ref_t addr) -{ - // check - tb_assert_and_check_return_val(impl && addr, tb_false); - - // check - tb_assert_and_check_return_val(size >= TB_DNS_HEADER_SIZE, tb_false); - - // init stream - tb_static_stream_t stream; - tb_static_stream_init(&stream, impl->data, size); - - // init header - tb_dns_header_t header; - header.id = tb_static_stream_read_u16_be(&stream); tb_static_stream_skip(&stream, 2); - header.question = tb_static_stream_read_u16_be(&stream); - header.answer = tb_static_stream_read_u16_be(&stream); - header.authority = tb_static_stream_read_u16_be(&stream); - header.resource = tb_static_stream_read_u16_be(&stream); - - // trace - tb_trace_d("response: size: %u", size); - tb_trace_d("response: id: 0x%04x", header.id); - tb_trace_d("response: question: %d", header.question); - tb_trace_d("response: answer: %d", header.answer); - tb_trace_d("response: authority: %d", header.authority); - tb_trace_d("response: resource: %d", header.resource); - tb_trace_d(""); - - // check header - tb_assert_and_check_return_val(header.id == TB_DNS_HEADER_MAGIC, tb_false); - - // skip questions, only one question now. - // name + question1 + question2 + ... - tb_assert_and_check_return_val(header.question == 1, tb_false); -#if 1 - tb_static_stream_skip_cstr(&stream); - tb_static_stream_skip(&stream, 4); -#else - tb_char_t* name = tb_static_stream_read_cstr(&stream); - //name = tb_dns_decode_name(name); - tb_assert_and_check_return_val(name, tb_false); - tb_static_stream_skip(&stream, 4); - tb_trace_d("response: name: %s", name); -#endif - - // decode answers - tb_size_t i = 0; - tb_size_t found = 0; - for (i = 0; i < header.answer; i++) - { - // decode answer - tb_dns_answer_t answer; - - // trace - tb_trace_d("response: answer: %d", i); - - // decode impl name - tb_char_t const* name = tb_dns_decode_name(&stream, answer.name); tb_used(name); - - // trace - tb_trace_d("response: name: %s", name); - - // decode resource - answer.res.type = tb_static_stream_read_u16_be(&stream); - answer.res.class_ = tb_static_stream_read_u16_be(&stream); - answer.res.ttl = tb_static_stream_read_u32_be(&stream); - answer.res.size = tb_static_stream_read_u16_be(&stream); - - // trace - tb_trace_d("response: type: %d", answer.res.type); - tb_trace_d("response: class: %d", answer.res.class_); - tb_trace_d("response: ttl: %d", answer.res.ttl); - tb_trace_d("response: size: %d", answer.res.size); - - // is ipv4? - if (answer.res.type == 1) - { - // get ipv4 - tb_byte_t b1 = tb_static_stream_read_u8(&stream); - tb_byte_t b2 = tb_static_stream_read_u8(&stream); - tb_byte_t b3 = tb_static_stream_read_u8(&stream); - tb_byte_t b4 = tb_static_stream_read_u8(&stream); - - // trace - tb_trace_d("response: ipv4: %u.%u.%u.%u", b1, b2, b3, b4); - - // save the first ip - if (!found) - { - // save it - if (addr) - { - // init ipv4 - tb_ipv4_t ipv4; - ipv4.u8[0] = b1; - ipv4.u8[1] = b2; - ipv4.u8[2] = b3; - ipv4.u8[3] = b4; - - // save ipv4 - tb_ipaddr_ipv4_set(addr, &ipv4); - } - - // found it - found = 1; - - // trace - tb_trace_d("response: "); - break; - } - } - else - { - // decode rdata - answer.rdata = (tb_byte_t const*)tb_dns_decode_name(&stream, answer.name); - - // trace - tb_trace_d("response: alias: %s", answer.rdata? (tb_char_t const*)answer.rdata : ""); - } - - // trace - tb_trace_d("response: "); - } - - // found it? - tb_check_return_val(found, tb_false); - - // ok - return tb_true; -} -static tb_bool_t tb_aicp_dns_reqt_func(tb_aice_ref_t aice); -static tb_bool_t tb_aicp_dns_resp_func(tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_URECV, tb_false); - - // the aicp - tb_aicp_ref_t aicp = (tb_aicp_ref_t)tb_aico_aicp(aice->aico); - tb_assert_and_check_return_val(aicp, tb_false); - - // the impl - tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)aice->priv; - tb_assert_and_check_return_val(impl, tb_false); - - // done - tb_ipaddr_t addr = {0}; - if (aice->state == TB_STATE_OK) - { - // trace - tb_trace_d("resp[%s]: aico: %p, server: %{ipaddr}, real: %lu", impl->host, impl->aico, &aice->u.urecv.addr, aice->u.urecv.real); - - // check - tb_assert_and_check_return_val(aice->u.urecv.real, tb_false); - - // done resp - tb_aicp_dns_resp_done(impl, aice->u.urecv.real, &addr); - } - // timeout or failed? - else - { - // trace - tb_trace_d("resp[%s]: aico: %p, state: %s", impl->host, impl->aico, tb_state_cstr(aice->state)); - } - - // ok or try to get ok from cache again if failed or timeout? - tb_bool_t from_cache = tb_false; - if (!tb_ipaddr_ip_is_empty(&addr) || (from_cache = tb_dns_cache_get(impl->host, &addr))) - { - // save to cache - if (!from_cache) tb_dns_cache_set(impl->host, &addr); - - // done func - impl->done.func((tb_aicp_dns_ref_t)impl, impl->host, &addr, impl->done.priv); - return tb_true; - } - - // try next server? - tb_bool_t ok = tb_false; - tb_ipaddr_ref_t server = &impl->list[impl->indx + 1]; - if (!tb_ipaddr_is_empty(server)) - { - // indx++ - impl->indx++; - - // init reqt - tb_size_t size = tb_aicp_dns_reqt_init(impl); - if (size) - { - // post reqt - ok = tb_aico_usend(aice->aico, server, impl->data, size, tb_aicp_dns_reqt_func, (tb_pointer_t)impl); - } - } - - // failed? done func - if (!ok) impl->done.func((tb_aicp_dns_ref_t)impl, impl->host, tb_null, impl->done.priv); - - // continue - return tb_true; -} -static tb_bool_t tb_aicp_dns_reqt_func(tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_USEND, tb_false); - - // the aicp - tb_aicp_ref_t aicp = (tb_aicp_ref_t)tb_aico_aicp(aice->aico); - tb_assert_and_check_return_val(aicp, tb_false); - - // the impl - tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)aice->priv; - tb_assert_and_check_return_val(impl && impl->done.func, tb_false); - - // done - tb_bool_t ok = tb_false; - if (aice->state == TB_STATE_OK) - { - // trace - tb_trace_d("reqt[%s]: aico: %p, server: %{ipaddr}, real: %lu", impl->host, impl->aico, &aice->u.usend.addr, aice->u.usend.real); - - // check - tb_assert_and_check_return_val(aice->u.usend.real, tb_false); - - // post resp - ok = tb_aico_urecv(aice->aico, impl->data, sizeof(impl->data), tb_aicp_dns_resp_func, (tb_pointer_t)impl); - } - // timeout or failed? - else - { - // trace - tb_trace_d("reqt[%s]: aico: %p, server: %{ipaddr}, state: %s", impl->host, impl->aico, &aice->u.usend.addr, tb_state_cstr(aice->state)); - - // the next server - tb_ipaddr_ref_t server = &impl->list[impl->indx + 1]; - if (!tb_ipaddr_is_empty(server)) - { - // indx++ - impl->indx++; - - // init reqt - tb_size_t size = tb_aicp_dns_reqt_init(impl); - if (size) - { - // post reqt - ok = tb_aico_usend(aice->aico, server, impl->data, size, tb_aicp_dns_reqt_func, (tb_pointer_t)impl); - } - } - } - - // failed? done func - if (!ok) impl->done.func((tb_aicp_dns_ref_t)impl, impl->host, tb_null, impl->done.priv); - - // continue - return tb_true; -} -static tb_bool_t tb_aicp_dns_clos_func(tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_CLOS, tb_false); - - // trace - tb_trace_d("exit: aico: %p: ok", aice->aico); - - // exit aico - tb_aico_exit(aice->aico); - - // ok - return tb_true; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_aicp_dns_ref_t tb_aicp_dns_init(tb_aicp_ref_t aicp) -{ - // check - tb_assert_and_check_return_val(aicp, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_aicp_dns_impl_t* impl = tb_null; - do - { - // make impl - impl = tb_malloc0_type(tb_aicp_dns_impl_t); - tb_assert_and_check_break(impl); - - // init aicp - impl->aicp = aicp; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (impl) tb_aicp_dns_exit((tb_aicp_dns_ref_t)impl); - impl = tb_null; - } - - // ok? - return (tb_aicp_dns_ref_t)impl; -} -tb_void_t tb_aicp_dns_kill(tb_aicp_dns_ref_t dns) -{ - // check - tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)dns; - tb_assert_and_check_return(impl); - - // trace - tb_trace_d("kill: aico: %p ..", impl->aico); - - // kill it - if (impl->aico) tb_aico_kill(impl->aico); -} -tb_void_t tb_aicp_dns_exit(tb_aicp_dns_ref_t dns) -{ - // check - tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)dns; - tb_assert_and_check_return(impl); - - // trace - tb_trace_d("exit: aico: %p ..", impl->aico); - - // clos aico - if (impl->aico) tb_aico_clos(impl->aico, tb_aicp_dns_clos_func, tb_null); - impl->aico = tb_null; - - // exit it - tb_free(impl); -} -tb_bool_t tb_aicp_dns_done(tb_aicp_dns_ref_t dns, tb_char_t const* host, tb_long_t timeout, tb_aicp_dns_done_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)dns; - tb_assert_and_check_return_val(impl && func && host && host[0], tb_false); - - // trace - tb_trace_d("done: aico: %p, host: %s: ..", impl->aico, host); - - // init func - impl->done.func = func; - impl->done.priv = priv; - - // save host - tb_strlcpy(impl->host, host, sizeof(impl->host)); - - // only address? ok - tb_ipaddr_t addr = {0}; - if (tb_ipaddr_ip_cstr_set(&addr, impl->host, TB_IPADDR_FAMILY_NONE)) - { - impl->done.func(dns, impl->host, &addr, impl->done.priv); - return tb_true; - } - - // try to lookup it from cache first - if (tb_dns_cache_get(impl->host, &addr)) - { - impl->done.func(dns, impl->host, &addr, impl->done.priv); - return tb_true; - } - - // init server list - if (!impl->size) impl->size = tb_dns_server_get(impl->list); - tb_check_return_val(impl->size, tb_false); - - // get the server - tb_ipaddr_ref_t server = &impl->list[impl->indx = 0]; - tb_assert_and_check_return_val(!tb_ipaddr_is_empty(server), tb_false); - - // init reqt - tb_size_t size = tb_aicp_dns_reqt_init(impl); - tb_assert_and_check_return_val(size, tb_false); - - // init it first if no aico - if (!impl->aico) - { - // init aico - impl->aico = tb_aico_init(impl->aicp); - tb_assert_and_check_return_val(impl->aico, tb_false); - - // open aico - if (!tb_aico_open_sock_from_type(impl->aico, TB_SOCKET_TYPE_UDP, tb_ipaddr_family(server))) return tb_false; - - // init timeout - tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_SEND, timeout); - tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_RECV, timeout); - } - - // post reqt - return tb_aico_usend(impl->aico, server, impl->data, size, tb_aicp_dns_reqt_func, (tb_pointer_t)impl); -} -tb_aicp_ref_t tb_aicp_dns_aicp(tb_aicp_dns_ref_t dns) -{ - // check - tb_aicp_dns_impl_t* impl = (tb_aicp_dns_impl_t*)dns; - tb_assert_and_check_return_val(impl && impl->aico, tb_null); - - // the aicp - return impl->aicp; -} diff --git a/core/src/tbox/src/tbox/asio/deprecated/dns.h b/core/src/tbox/src/tbox/asio/deprecated/dns.h deleted file mode 100644 index 8b5ca3662..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/dns.h +++ /dev/null @@ -1,104 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file dns.h - * @ingroup asio - * - */ -#ifndef TB_ASIO_DNS_H -#define TB_ASIO_DNS_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "aicp.h" -#include "../../network/ipaddr.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the aicp dns ref type -typedef __tb_typeref__(aicp_dns); - -/// the aicp dns done func type -typedef tb_void_t (*tb_aicp_dns_done_func_t)(tb_aicp_dns_ref_t dns, tb_char_t const* host, tb_ipaddr_ref_t addr, tb_cpointer_t priv); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init the dns - * - * @param aicp the aicp - * - * @return the dns - */ -__tb_deprecated__ -tb_aicp_dns_ref_t tb_aicp_dns_init(tb_aicp_ref_t aicp); - -/*! kill the dns - * - * @param dns the dns - */ -__tb_deprecated__ -tb_void_t tb_aicp_dns_kill(tb_aicp_dns_ref_t dns); - -/*! exit the dns - * - * @param dns the dns - */ -__tb_deprecated__ -tb_void_t tb_aicp_dns_exit(tb_aicp_dns_ref_t dns); - -/*! done the dns - * - * @param dns the dns - * @param host the host - * @param timeout the timeout, ms - * @param func the done func - * @param priv the func private data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_dns_done(tb_aicp_dns_ref_t dns, tb_char_t const* host, tb_long_t timeout, tb_aicp_dns_done_func_t func, tb_cpointer_t priv); - -/*! the dns aicp - * - * @param handle the dns handle - * - * @return the aicp - */ -__tb_deprecated__ -tb_aicp_ref_t tb_aicp_dns_aicp(tb_aicp_dns_ref_t dns); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/http.c b/core/src/tbox/src/tbox/asio/deprecated/http.c deleted file mode 100644 index cab80df34..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/http.c +++ /dev/null @@ -1,1770 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file http.c - * @ingroup asio - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "aicp_http" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "http.h" -#include "aico.h" -#include "aicp.h" -#include "../../zip/zip.h" -#include "../../string/string.h" -#include "../../stream/stream.h" -#include "../../network/network.h" -#include "../../platform/platform.h" -#include "../../algorithm/algorithm.h" -#include "../../container/container.h" -#include "../../network/impl/http/date.h" -#include "../../network/impl/http/option.h" -#include "../../network/impl/http/status.h" -#include "../../network/impl/http/method.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the aicp http impl open and read type -typedef struct __tb_aicp_http_open_read_t -{ - // the func - tb_aicp_http_read_func_t func; - - // the priv - tb_cpointer_t priv; - - // the size - tb_size_t size; - -}tb_aicp_http_open_read_t; - -// the aicp http impl open and seek type -typedef struct __tb_aicp_http_open_seek_t -{ - // the func - tb_aicp_http_seek_func_t func; - - // the priv - tb_cpointer_t priv; - - // the offset - tb_hize_t offset; - -}tb_aicp_http_open_seek_t; - -// the aicp http impl close opening type -typedef struct __tb_aicp_http_clos_opening_t -{ - // the func - tb_aicp_http_open_func_t func; - - // the priv - tb_cpointer_t priv; - - // the state - tb_size_t state; - -}tb_aicp_http_clos_opening_t; - -// the aicp http impl type -typedef struct __tb_aicp_http_impl_t -{ - // the option - tb_http_option_t option; - - // the status - tb_http_status_t status; - - // the stream - tb_async_stream_ref_t stream; - - // the sstream for sock - tb_async_stream_ref_t sstream; - - // the cstream for chunked - tb_async_stream_ref_t cstream; - - // the zstream for gzip/deflate - tb_async_stream_ref_t zstream; - - // the request head - tb_hash_map_ref_t head; - - // the cookies - tb_string_t cookies; - - // the transfer for post - tb_async_transfer_ref_t transfer; - - /* the state - * - * TB_STATE_CLOSED - * TB_STATE_OPENED - * TB_STATE_OPENING - * TB_STATE_KILLING - */ - tb_atomic_t state; - - // the line data - tb_string_t line_data; - - // the line size - tb_size_t line_size; - - // the cache data - tb_buffer_t cache_data; - - // the cache read - tb_size_t cache_read; - - // the redirect tryn - tb_size_t redirect_tryn; - - // the content read - tb_hize_t content_read; - - // the clos opening - tb_aicp_http_clos_opening_t clos_opening; - - // the open and read, writ, seek, ... - union - { - tb_aicp_http_open_read_t read; - tb_aicp_http_open_seek_t seek; - - } open_and; - - // the func - union - { - tb_aicp_http_open_func_t open; - tb_aicp_http_read_func_t read; - tb_aicp_http_seek_func_t seek; - tb_aicp_http_task_func_t task; - tb_aicp_http_clos_func_t clos; - - } func; - - // the priv - tb_cpointer_t priv; - -}tb_aicp_http_impl_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * declaration - */ -static tb_bool_t tb_aicp_http_open_done(tb_aicp_http_impl_t* impl); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_char_t const* tb_aicp_http_head_format(tb_aicp_http_impl_t* impl, tb_hize_t post_size, tb_size_t* head_size, tb_size_t* state) -{ - // check - tb_assert_and_check_return_val(impl && head_size, tb_null); - - // clear line data - tb_string_clear(&impl->line_data); - - // init the head value - tb_char_t data[8192]; - tb_static_string_t value; - if (!tb_static_string_init(&value, data, sizeof(data))) return tb_null; - - // init method - tb_char_t const* method = tb_http_method_cstr(impl->option.method); - tb_assert_and_check_return_val(method, tb_null); - - // init path - tb_char_t const* path = tb_url_path(&impl->option.url); - tb_assert_and_check_return_val(path, tb_null); - - // init args - tb_char_t const* args = tb_url_args(&impl->option.url); - - // init host - tb_char_t const* host = tb_url_host(&impl->option.url); - tb_assert_and_check_return_val(host, tb_null); - tb_hash_map_insert(impl->head, "Host", host); - - // init accept - tb_hash_map_insert(impl->head, "Accept", "*/*"); - - // init connection - tb_hash_map_insert(impl->head, "Connection", impl->status.balived? "keep-alive" : "close"); - - // init cookies - tb_bool_t cookie = tb_false; - if (impl->option.cookies) - { - // update cookie - if (tb_cookies_get(impl->option.cookies, host, path, tb_url_ssl(&impl->option.url), &impl->cookies)) - { - tb_hash_map_insert(impl->head, "Cookie", tb_string_cstr(&impl->cookies)); - cookie = tb_true; - } - } - - // no cookie? remove it - if (!cookie) tb_hash_map_remove(impl->head, "Cookie"); - - // init range - if (impl->option.range.bof && impl->option.range.eof >= impl->option.range.bof) - tb_static_string_cstrfcpy(&value, "bytes=%llu-%llu", impl->option.range.bof, impl->option.range.eof); - else if (impl->option.range.bof && !impl->option.range.eof) - tb_static_string_cstrfcpy(&value, "bytes=%llu-", impl->option.range.bof); - else if (!impl->option.range.bof && impl->option.range.eof) - tb_static_string_cstrfcpy(&value, "bytes=0-%llu", impl->option.range.eof); - else if (impl->option.range.bof > impl->option.range.eof) - { - // save state - if (state) *state = TB_STATE_HTTP_RANGE_INVALID; - return tb_null; - } - - // update range - if (tb_static_string_size(&value)) tb_hash_map_insert(impl->head, "Range", tb_static_string_cstr(&value)); - // remove range - else tb_hash_map_remove(impl->head, "Range"); - - // init post - if (impl->option.method == TB_HTTP_METHOD_POST) - { - // append post size - tb_static_string_cstrfcpy(&value, "%llu", post_size); - tb_hash_map_insert(impl->head, "Content-Length", tb_static_string_cstr(&value)); - } - // remove post - else tb_hash_map_remove(impl->head, "Content-Length"); - - // replace the custom head - tb_char_t const* head_data = (tb_char_t const*)tb_buffer_data(&impl->option.head_data); - tb_char_t const* head_tail = head_data + tb_buffer_size(&impl->option.head_data); - while (head_data < head_tail) - { - // the name and data - tb_char_t const* name = head_data; - tb_char_t const* data = head_data + tb_strlen(name) + 1; - tb_check_break(data < head_tail); - - // replace it - tb_hash_map_insert(impl->head, name, data); - - // next - head_data = data + tb_strlen(data) + 1; - } - - // exit the head value - tb_static_string_exit(&value); - - // check head - tb_assert_and_check_return_val(tb_hash_map_size(impl->head), tb_null); - - // append method - tb_string_cstrcat(&impl->line_data, method); - - // append ' ' - tb_string_chrcat(&impl->line_data, ' '); - - // encode path - tb_url_encode2(path, tb_strlen(path), data, sizeof(data) - 1); - path = data; - - // append path - tb_string_cstrcat(&impl->line_data, path); - - // append args if exists - if (args) - { - // append '?' - tb_string_chrcat(&impl->line_data, '?'); - - // encode args - tb_url_encode2(args, tb_strlen(args), data, sizeof(data) - 1); - args = data; - - // append args - tb_string_cstrcat(&impl->line_data, args); - } - - // append ' ' - tb_string_chrcat(&impl->line_data, ' '); - - // append version, HTTP/1.1 - tb_string_cstrfcat(&impl->line_data, "HTTP/1.%1u\r\n", impl->option.version); - - // append key: value - tb_for_all (tb_hash_map_item_ref_t, item, impl->head) - { - if (item && item->name && item->data) - tb_string_cstrfcat(&impl->line_data, "%s: %s\r\n", (tb_char_t const*)item->name, (tb_char_t const*)item->data); - } - - // append end - tb_string_cstrcat(&impl->line_data, "\r\n"); - - // save the head size - *head_size = tb_string_size(&impl->line_data); - - // ok - return tb_string_cstr(&impl->line_data); -} -static tb_bool_t tb_aicp_http_open_read_func(tb_aicp_http_ref_t http, tb_size_t state, tb_http_status_t const* status, tb_cpointer_t priv) -{ - // check - tb_aicp_http_open_read_t* open_read = (tb_aicp_http_open_read_t*)priv; - tb_assert_and_check_return_val(http && status && open_read && open_read->func, tb_false); - - // done - tb_bool_t ok = tb_true; - do - { - // ok? - tb_check_break(state == TB_STATE_OK); - - // reset state - state = TB_STATE_UNKNOWN_ERROR; - - // read it - if (!tb_aicp_http_read(http, open_read->size, open_read->func, open_read->priv)) break; - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - ok = open_read->func(http, state, tb_null, 0, open_read->size, open_read->priv); - } - - // ok? - return ok; -} -static tb_bool_t tb_aicp_http_open_seek_func(tb_aicp_http_ref_t http, tb_size_t state, tb_http_status_t const* status, tb_cpointer_t priv) -{ - // check - tb_aicp_http_open_seek_t* open_seek = (tb_aicp_http_open_seek_t*)priv; - tb_assert_and_check_return_val(http && status && open_seek && open_seek->func, tb_false); - - // done - tb_bool_t ok = tb_true; - do - { - // ok? - tb_check_break(state == TB_STATE_OK); - - // reset state - state = TB_STATE_UNKNOWN_ERROR; - - // seek it - if (!tb_aicp_http_seek(http, open_seek->offset, open_seek->func, open_seek->priv)) break; - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - ok = open_seek->func(http, state, 0, open_seek->priv); - } - - // ok? - return ok; -} -/* - * HTTP/1.1 206 Partial Content - * Date: Fri, 23 Apr 2010 05:25:45 GMT - * Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6-2ubuntu4.5 with Suhosin-Patch - * Last-Modified: Mon, 08 Mar 2010 09:58:09 GMT - * ETag: "6cc014-8f47f-481471a322e40" - * Accept-Ranges: bytes - * Content-Length: 586879 - * Content-Range: bytes 0-586878/586879 - * Connection: close - * Content-Type: application/x-shockwave-flash - */ -static tb_bool_t tb_aicp_http_head_resp_done(tb_aicp_http_impl_t* impl) -{ - // check - tb_assert_and_check_return_val(impl && impl->sstream, tb_false); - - // the line and size - tb_char_t const* line = tb_string_cstr(&impl->line_data); - tb_size_t size = tb_string_size(&impl->line_data); - tb_assert_and_check_return_val(line && size, tb_false); - - // the first line? - tb_char_t const* p = line; - if (!impl->line_size) - { - // check http response - if (tb_strnicmp(p, "HTTP/1.", 7)) - { - // failed - tb_assert(0); - return tb_false; - } - - // seek to the http version - p += 7; - tb_assert_and_check_return_val(*p, tb_false); - - // parse version - tb_assert_and_check_return_val((*p - '0') < 2, tb_false); - impl->status.version = *p - '0'; - - // seek to the http code - p++; while (tb_isspace(*p)) p++; - - // parse code - tb_assert_and_check_return_val(*p && tb_isdigit(*p), tb_false); - impl->status.code = tb_stou32(p); - - // save state - if (impl->status.code == 200 || impl->status.code == 206) - impl->status.state = TB_STATE_OK; - else if (impl->status.code == 204) - impl->status.state = TB_STATE_HTTP_RESPONSE_204; - else if (impl->status.code >= 300 && impl->status.code <= 307) - impl->status.state = TB_STATE_HTTP_RESPONSE_300 + (impl->status.code - 300); - else if (impl->status.code >= 400 && impl->status.code <= 416) - impl->status.state = TB_STATE_HTTP_RESPONSE_400 + (impl->status.code - 400); - else if (impl->status.code >= 500 && impl->status.code <= 507) - impl->status.state = TB_STATE_HTTP_RESPONSE_500 + (impl->status.code - 500); - else impl->status.state = TB_STATE_HTTP_RESPONSE_UNK; - - // check state code: 4xx & 5xx - if (impl->status.code >= 400 && impl->status.code < 600) return tb_false; - } - // key: value? - else - { - // seek to value - while (*p && *p != ':') p++; - tb_assert_and_check_return_val(*p, tb_false); - p++; while (*p && tb_isspace(*p)) p++; - - // no value - tb_check_return_val(*p, tb_true); - - // parse content size - if (!tb_strnicmp(line, "Content-Length", 14)) - { - impl->status.content_size = tb_stou64(p); - if (impl->status.document_size < 0) - impl->status.document_size = impl->status.content_size; - } - // parse content range: "bytes $from-$to/$document_size" - else if (!tb_strnicmp(line, "Content-Range", 13)) - { - tb_hize_t from = 0; - tb_hize_t to = 0; - tb_hize_t document_size = 0; - if (!tb_strncmp(p, "bytes ", 6)) - { - p += 6; - from = tb_stou64(p); - while (*p && *p != '-') p++; - if (*p && *p++ == '-') to = tb_stou64(p); - while (*p && *p != '/') p++; - if (*p && *p++ == '/') document_size = tb_stou64(p); - } - // no stream, be able to seek - impl->status.bseeked = 1; - impl->status.document_size = document_size; - if (impl->status.content_size < 0) - { - if (from && to > from) impl->status.content_size = to - from; - else if (!from && to) impl->status.content_size = to; - else if (from && !to && document_size > from) impl->status.content_size = document_size - from; - else impl->status.content_size = document_size; - } - } - // parse accept-ranges: "bytes " - else if (!tb_strnicmp(line, "Accept-Ranges", 13)) - { - // no stream, be able to seek - impl->status.bseeked = 1; - } - // parse content type - else if (!tb_strnicmp(line, "Content-Type", 12)) - { - tb_string_cstrcpy(&impl->status.content_type, p); - tb_assert_and_check_return_val(tb_string_size(&impl->status.content_type), tb_false); - } - // parse transfer encoding - else if (!tb_strnicmp(line, "Transfer-Encoding", 17)) - { - if (!tb_stricmp(p, "chunked")) impl->status.bchunked = 1; - } - // parse content encoding - else if (!tb_strnicmp(line, "Content-Encoding", 16)) - { - if (!tb_stricmp(p, "gzip")) impl->status.bgzip = 1; - else if (!tb_stricmp(p, "deflate")) impl->status.bdeflate = 1; - } - // parse location - else if (!tb_strnicmp(line, "Location", 8)) - { - // redirect? check code: 301 - 307 - tb_assert_and_check_return_val(impl->status.code > 300 && impl->status.code < 308, tb_false); - - // save location - tb_string_cstrcpy(&impl->status.location, p); - } - // parse connection - else if (!tb_strnicmp(line, "Connection", 10)) - { - // keep alive? - impl->status.balived = !tb_stricmp(p, "close")? 0 : 1; - - // ctrl stream for sock - if (!tb_async_stream_ctrl(impl->sstream, TB_STREAM_CTRL_SOCK_KEEP_ALIVE, impl->status.balived? tb_true : tb_false)) return tb_false; - } - // parse cookies - else if (impl->option.cookies && !tb_strnicmp(line, "Set-Cookie", 10)) - { - // the host - tb_char_t const* host = tb_null; - tb_aicp_http_ctrl((tb_aicp_http_ref_t)impl, TB_HTTP_OPTION_GET_HOST, &host); - - // the path - tb_char_t const* path = tb_null; - tb_aicp_http_ctrl((tb_aicp_http_ref_t)impl, TB_HTTP_OPTION_GET_PATH, &path); - - // is ssl? - tb_bool_t bssl = tb_false; - tb_aicp_http_ctrl((tb_aicp_http_ref_t)impl, TB_HTTP_OPTION_GET_SSL, &bssl); - - // set cookies - tb_cookies_set(impl->option.cookies, host, path, bssl, p); - } - } - - // ok - return tb_true; -} -static tb_bool_t tb_aicp_http_open_func(tb_aicp_http_impl_t* impl, tb_size_t state, tb_aicp_http_open_func_t func, tb_cpointer_t priv); -static tb_bool_t tb_aicp_http_head_redt_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->stream && impl->func.open, tb_false); - - // trace - tb_trace_d("head: redt: real: %lu, size: %lu, state: %s", real, size, tb_state_cstr(state)); - - // done - do - { - // killed? - if (TB_STATE_KILLING == tb_atomic_get(&impl->state)) - { - state = TB_STATE_KILLED; - break; - } - - // ok? - if (state == TB_STATE_OK) - { - // save read - impl->content_read += real; - - // continue? - if (impl->status.content_size < 0 || impl->content_read < (tb_hize_t)impl->status.content_size) return tb_true; - } - - // ok? - tb_check_break(state == TB_STATE_OK || state == TB_STATE_CLOSED); - - // redirect failed - state = TB_STATE_HTTP_REDIRECT_FAILED; - - // done location url - tb_char_t const* location = tb_string_cstr(&impl->status.location); - tb_assert_and_check_break(location); - - // trace - tb_trace_d("redirect: %s", location); - - // only file path? - if (tb_url_protocol_probe(location) == TB_URL_PROTOCOL_FILE) tb_url_path_set(&impl->option.url, location); - // full url? - else - { - // set url - if (!tb_url_cstr_set(&impl->option.url, location)) break; - } - - // done open - if (!tb_aicp_http_open_done(impl)) break; - - // ok - return tb_false; - - } while (0); - - // done func - tb_aicp_http_open_func(impl, state, impl->func.open, impl->priv); - - // break - return tb_false; -} -static tb_bool_t tb_aicp_http_head_read_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->stream && impl->func.open, tb_false); - - // trace - tb_trace_d("head: read: %s, real: %lu, size: %lu, state: %s", tb_url_cstr(&impl->option.url), real, size, tb_state_cstr(state)); - - // done - do - { - // ok? - tb_check_break(state == TB_STATE_OK); - - // reset state - state = TB_STATE_UNKNOWN_ERROR; - - // walk - tb_long_t ok = 0; - tb_char_t ch = '\0'; - tb_char_t const* p = (tb_char_t const*)data; - tb_char_t const* e = p + real; - while (p < e) - { - // the char - ch = *p++; - - // error end? - if (!ch) - { - ok = -1; - tb_assert(0); - break; - } - - // append char to line - if (ch != '\n') tb_string_chrcat(&impl->line_data, ch); - // is line end? - else - { - // strip '\r' if exists - tb_char_t const* pb = tb_string_cstr(&impl->line_data); - tb_size_t pn = tb_string_size(&impl->line_data); - if (!pb || !pn) - { - ok = -1; - tb_assert(0); - break; - } - - if (pb[pn - 1] == '\r') - tb_string_strip(&impl->line_data, pn - 1); - - // trace - tb_trace_d("response: %s", pb); - - // do callback - if (impl->option.head_func && !impl->option.head_func(pb, impl->option.head_priv)) - { - ok = -1; - tb_assert(0); - break; - } - - // end? - if (!tb_string_size(&impl->line_data)) - { - // ok - ok = 1; - break; - } - - // done the head response - if (!tb_aicp_http_head_resp_done(impl)) - { - // save the error state - if (impl->status.state != TB_STATE_OK) state = impl->status.state; - - // error - ok = -1; - break; - } - - // clear line data - tb_string_clear(&impl->line_data); - - // line++ - impl->line_size++; - } - } - - // continue ? - if (!ok) return tb_true; - // end? - else if (ok > 0) - { - // trace - tb_trace_d("head: read: end, left: %lu", e - p); - - // trace - tb_trace_d("response: ok"); - - // redirect? - if (tb_string_size(&impl->status.location) && impl->redirect_tryn++ < impl->option.redirect) - { - // save the redirect read - impl->content_read = e - p; - - // read the left data - if (impl->status.content_size < 0 || impl->content_read < (tb_hize_t)impl->status.content_size) - { - if (!tb_async_stream_read(impl->stream, 0, tb_aicp_http_head_redt_func, impl)) break; - } - // no left data, redirect it directly - else tb_aicp_http_head_redt_func(impl->stream, TB_STATE_OK, tb_null, 0, 0, impl); - return tb_false; - } - - // switch to cstream if chunked - if (impl->status.bchunked) - { - // init cstream - if (impl->cstream) - { - if (!tb_async_stream_ctrl(impl->cstream, TB_STREAM_CTRL_FLTR_SET_STREAM, impl->stream)) break; - } - else impl->cstream = tb_async_stream_init_filter_from_chunked(impl->stream, tb_true); - tb_assert_and_check_break(impl->cstream); - - // push the left data to filter - if (p < e) - { - // the filter - tb_filter_ref_t filter = tb_null; - if (!tb_async_stream_ctrl(impl->cstream, TB_STREAM_CTRL_FLTR_GET_FILTER, &filter)) break; - tb_assert_and_check_break(filter); - - // push data - if (!tb_filter_push(filter, (tb_byte_t const*)p, e - p)) break; - p = e; - } - - // try to open cstream directly, because the stream have been opened - if (!tb_async_stream_open_try(impl->cstream)) break; - - // using cstream - impl->stream = impl->cstream; - - // disable seek - impl->status.bseeked = 0; - } - - // switch to zstream if gzip or deflate - if (impl->option.bunzip && (impl->status.bgzip || impl->status.bdeflate)) - { -#ifdef TB_CONFIG_PACKAGE_HAVE_ZLIB - // init zstream - if (impl->zstream) - { - if (!tb_async_stream_ctrl(impl->zstream, TB_STREAM_CTRL_FLTR_SET_STREAM, impl->stream)) break; - } - else impl->zstream = tb_async_stream_init_filter_from_zip(impl->stream, impl->status.bgzip? TB_ZIP_ALGO_GZIP : TB_ZIP_ALGO_ZLIB, TB_ZIP_ACTION_INFLATE); - tb_assert_and_check_break(impl->zstream); - - // the filter - tb_filter_ref_t filter = tb_null; - if (!tb_async_stream_ctrl(impl->zstream, TB_STREAM_CTRL_FLTR_GET_FILTER, &filter)) break; - tb_assert_and_check_break(filter); - - // ctrl filter - if (!tb_filter_ctrl(filter, TB_FILTER_CTRL_ZIP_SET_ALGO, impl->status.bgzip? TB_ZIP_ALGO_GZIP : TB_ZIP_ALGO_ZLIB, TB_ZIP_ACTION_INFLATE)) break; - - // limit the filter input size - if (impl->status.content_size > 0) tb_filter_limit(filter, impl->status.content_size); - - // push the left data to filter - if (p < e) - { - // push data - if (!tb_filter_push(filter, (tb_byte_t const*)p, e - p)) break; - p = e; - } - - // try to open zstream directly, because the stream have been opened - if (!tb_async_stream_open_try(impl->zstream)) break; - - // using zstream - impl->stream = impl->zstream; - - // disable seek - impl->status.bseeked = 0; -#else - // trace - tb_trace_w("gzip is not supported now! please enable it from config if you need it."); - - // not supported - state = TB_STATE_HTTP_GZIP_NOT_SUPPORTED; - break; -#endif - } - - // cache the left data - if (p < e) tb_buffer_memncat(&impl->cache_data, (tb_byte_t const*)p, e - p); - p = e; - - // ok - state = TB_STATE_OK; - - // dump status -#if defined(__tb_debug__) && TB_TRACE_MODULE_DEBUG - tb_http_status_dump(&impl->status); -#endif - } - // error? - else - { - // trace - tb_trace_d("head: read: %s, error, state: %s", tb_url_cstr(&impl->option.url), tb_state_cstr(state)); - } - - } while (0); - - // done func - tb_aicp_http_open_func(impl, state, impl->func.open, impl->priv); - - // break - return tb_false; -} -static tb_bool_t tb_aicp_http_head_post_func(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->stream && impl->func.open, tb_false); - - // trace - tb_trace_d("head: post: percent: %llu%%, size: %lu, state: %s", size > 0? (offset * 100 / size) : 0, save, tb_state_cstr(state)); - - // done - tb_bool_t bpost = tb_false; - do - { - // done func - if (impl->option.post_func && !impl->option.post_func(state, offset, size, save, rate, impl->option.post_priv)) - { - state = TB_STATE_UNKNOWN_ERROR; - break; - } - - // ok? continue to post - if (state == TB_STATE_OK) bpost = tb_true; - // closed? read head - else if (state == TB_STATE_CLOSED) - { - // reset state - state = TB_STATE_UNKNOWN_ERROR; - - // clear line size - impl->line_size = 0; - - // clear line data - tb_string_clear(&impl->line_data); - - // clear cache data - tb_buffer_clear(&impl->cache_data); - impl->cache_read = 0; - - // post read - if (!tb_async_stream_read(impl->stream, 0, tb_aicp_http_head_read_func, impl)) break; - } - // failed? - else break; - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - tb_aicp_http_open_func(impl, state, impl->func.open, impl->priv); - } - - // ok? - return bpost; -} -static tb_bool_t tb_aicp_http_head_writ_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->stream && impl->func.open, tb_false); - - // trace - tb_trace_d("head: writ: %s, real: %lu, size: %lu, state: %s", tb_url_cstr(&impl->option.url), real, size, tb_state_cstr(state)); - - // done - tb_bool_t bwrit = tb_false; - do - { - // ok? - tb_check_break(state == TB_STATE_OK); - - // killed? - if (TB_STATE_KILLING == tb_atomic_get(&impl->state)) - { - state = TB_STATE_KILLED; - break; - } - - // reset state - state = TB_STATE_UNKNOWN_ERROR; - - // not finished? continue it - if (real < size) - { - // continue to writ - bwrit = tb_true; - } - // finished? post data - else if (impl->option.method == TB_HTTP_METHOD_POST) - { - // check - tb_assert_and_check_break(impl->transfer); - - // post data - if (!tb_async_transfer_done(impl->transfer, tb_aicp_http_head_post_func, impl)) break; - } - // finished? read data - else - { - // clear line size - impl->line_size = 0; - - // clear line data - tb_string_clear(&impl->line_data); - - // clear cache data - tb_buffer_clear(&impl->cache_data); - impl->cache_read = 0; - - // post read - if (!tb_async_stream_read(impl->stream, 0, tb_aicp_http_head_read_func, impl)) break; - } - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - tb_aicp_http_open_func(impl, state, impl->func.open, impl->priv); - } - - // ok? - return bwrit; -} -static tb_bool_t tb_aicp_http_post_open_func(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->stream && impl->func.open, tb_false); - - // trace - tb_trace_d("post: open: offset: %lu, size: %lu, state: %s", offset, size, tb_state_cstr(state)); - - // done - tb_bool_t ok = tb_true; - do - { - // ok? - tb_check_break(state == TB_STATE_OK); - - // reset state - state = TB_STATE_UNKNOWN_ERROR; - - // no post size? - if (size < 0) - { - state = TB_STATE_HTTP_POST_FAILED; - break; - } - - // the head data and size - tb_size_t head_size = 0; - tb_char_t const* head_data = tb_aicp_http_head_format(impl, size, &head_size, &state); - tb_check_break(head_data && head_size); - - // trace - tb_trace_d("request[%lu]:\n%s", head_size, head_data); - - // post writ head - if (!tb_async_stream_writ(impl->stream, (tb_byte_t const*)head_data, head_size, tb_aicp_http_head_writ_func, impl)) break; - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - tb_aicp_http_open_func(impl, state, impl->func.open, impl->priv); - } - - // ok? - return ok; -} -static tb_bool_t tb_aicp_http_sock_open_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->stream && impl->func.open, tb_false); - - // trace - tb_trace_d("sock: open: state: %s", tb_state_cstr(state)); - - // done - tb_bool_t ok = tb_true; - do - { - // ok? - tb_check_break(state == TB_STATE_OK); - - // killed? - if (TB_STATE_KILLING == tb_atomic_get(&impl->state)) - { - state = TB_STATE_KILLED; - break; - } - - // reset state - state = TB_STATE_UNKNOWN_ERROR; - - // get? - if (impl->option.method == TB_HTTP_METHOD_GET) - { - // the head data and size - tb_size_t head_size = 0; - tb_char_t const* head_data = tb_aicp_http_head_format(impl, 0, &head_size, tb_null); - tb_check_break(head_data && head_size); - - // trace - tb_trace_d("request:\n%s", head_data); - - // post writ head - ok = tb_async_stream_open_writ(impl->stream, (tb_byte_t const*)head_data, head_size, tb_aicp_http_head_writ_func, impl); - } - // post? - else if (impl->option.method == TB_HTTP_METHOD_POST) - { - // init transfer - if (!impl->transfer) impl->transfer = tb_async_transfer_init(tb_async_stream_aicp(impl->stream), tb_false); - tb_assert_and_check_break(impl->transfer); - - // init transfer istream - tb_char_t const* url = tb_url_cstr(&impl->option.post_url); - if (impl->option.post_data && impl->option.post_size) - { - if (!tb_async_transfer_init_istream_from_data(impl->transfer, impl->option.post_data, impl->option.post_size)) break; - } - else if (url) - { - if (!tb_async_transfer_init_istream_from_url(impl->transfer, url)) break; - } - - // init transfer ostream - if (!tb_async_transfer_init_ostream(impl->transfer, impl->stream)) break; - - // limit rate - if (impl->option.post_lrate) tb_async_transfer_limitrate(impl->transfer, impl->option.post_lrate); - - // open transfer - ok = tb_async_transfer_open(impl->transfer, 0, tb_aicp_http_post_open_func, impl); - } - else tb_assert_and_check_break(0); - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - tb_aicp_http_open_func(impl, state, impl->func.open, impl->priv); - } - - // ok? - return ok; -} -static tb_bool_t tb_aicp_http_read_func(tb_async_stream_ref_t stream, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->stream && impl->func.read, tb_false); - - // ok? update the content read - if (state == TB_STATE_OK) impl->content_read += real; - - // trace - tb_trace_d("read: %s, real: %lu, offset: %llu <? %llu, state: %s", tb_url_cstr(&impl->option.url), real, impl->content_read, impl->status.content_size, tb_state_cstr(state)); - - // done func - tb_bool_t ok = impl->func.read((tb_aicp_http_ref_t)impl, state, data, real, size, impl->priv); - - // end? - if (ok && state == TB_STATE_OK && impl->status.content_size >= 0 && impl->content_read >= (tb_hize_t)impl->status.content_size) - { - // done func: closed - impl->func.read((tb_aicp_http_ref_t)impl, TB_STATE_CLOSED, data, 0, size, impl->priv); - - // break reading - ok = tb_false; - } - - // ok? - return ok; -} -static tb_bool_t tb_aicp_http_task_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->stream && impl->func.task, tb_false); - - // trace - tb_trace_d("task: state: %s", tb_state_cstr(state)); - - // done func - return impl->func.task((tb_aicp_http_ref_t)impl, state, impl->priv); -} -static tb_void_t tb_aicp_http_clos_clear(tb_aicp_http_impl_t* impl) -{ - // check - tb_assert_and_check_return(impl && impl->stream); - - // reset stream - impl->stream = impl->sstream; - - // clear the content read size - impl->content_read = 0; - - // closed - tb_atomic_set(&impl->state, TB_STATE_CLOSED); -} -static tb_void_t tb_aicp_http_clos_func(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return(impl && impl->stream && impl->func.clos); - - // trace - tb_trace_d("clos: notify: .."); - - // clear it - tb_aicp_http_clos_clear(impl); - - // done func - impl->func.clos((tb_aicp_http_ref_t)impl, state, impl->priv); - - // trace - tb_trace_d("clos: notify: ok"); -} -static tb_void_t tb_aicp_http_clos_transfer_func(tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return(impl && impl->stream && impl->func.clos); - - // trace - tb_trace_d("clos: transfer: notify: .."); - - // done func directly, because the stream have been closed by transfer - tb_aicp_http_clos_func(impl->stream, state, impl); - - // trace - tb_trace_d("clos: transfer: notify: ok"); -} -static tb_void_t tb_aicp_http_clos_opening_func(tb_aicp_http_ref_t http, tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return(impl && impl->clos_opening.func); - - // trace - tb_trace_d("clos: opening"); - - // done - impl->status.state = impl->clos_opening.state; - impl->clos_opening.func(http, impl->status.state, &impl->status, impl->clos_opening.priv); -} -static tb_void_t tb_aicp_http_open_clos(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return(impl && impl->stream && impl->func.open); - - // done - tb_bool_t ok = tb_false; - do - { - // check - tb_assert_and_check_break(state == TB_STATE_OK); - - // killed? - if (TB_STATE_KILLING == tb_atomic_get(&impl->state)) - { - state = TB_STATE_KILLED; - break; - } - - // reset state - state = TB_STATE_HTTP_UNKNOWN_ERROR; - - // reset stream - impl->stream = impl->sstream; - - // the host is changed? - tb_bool_t host_changed = tb_true; - tb_char_t const* host_old = tb_null; - tb_char_t const* host_new = tb_url_host(&impl->option.url); - tb_async_stream_ctrl(impl->stream, TB_STREAM_CTRL_GET_HOST, &host_old); - if (host_old && host_new && !tb_stricmp(host_old, host_new)) host_changed = tb_false; - - // trace - tb_trace_d("connect: host: %s", host_changed? "changed" : "keep"); - - // ctrl stream - if (!tb_async_stream_ctrl(impl->stream, TB_STREAM_CTRL_SET_URL, tb_url_cstr(&impl->option.url))) break; - if (!tb_async_stream_ctrl(impl->stream, TB_STREAM_CTRL_SET_TIMEOUT, impl->option.timeout)) break; - - // dump option -#if defined(__tb_debug__) && TB_TRACE_MODULE_DEBUG - tb_http_option_dump(&impl->option); -#endif - - // clear status - tb_http_status_cler(&impl->status, host_changed); - - // open the stream - ok = tb_async_stream_open(impl->stream, tb_aicp_http_sock_open_func, impl); - - } while (0); - - // failed? - if (!ok) - { - // done func - tb_aicp_http_open_func(impl, state, impl->func.open, impl->priv); - } -} -static tb_void_t tb_aicp_http_open_clos_transfer(tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)priv; - tb_assert_and_check_return(impl && impl->stream); - - // done func directly, because the stream have been closed by transfer - tb_aicp_http_open_clos(impl->stream, state, impl); -} -static tb_bool_t tb_aicp_http_open_done(tb_aicp_http_impl_t* impl) -{ - // check - tb_assert_and_check_return_val(impl && impl->stream && impl->func.open, tb_false); - - // close transfer - if (impl->transfer) return tb_async_transfer_clos(impl->transfer, tb_aicp_http_open_clos_transfer, impl); - // close stream - else return tb_async_stream_clos(impl->stream, tb_aicp_http_open_clos, impl); -} -static tb_bool_t tb_aicp_http_open_func(tb_aicp_http_impl_t* impl, tb_size_t state, tb_aicp_http_open_func_t func, tb_cpointer_t priv) -{ - // check - tb_assert_and_check_return_val(impl, tb_false); - - // ok? - tb_bool_t ok = tb_true; - if (state == TB_STATE_OK) - { - // opened - tb_atomic_set(&impl->state, TB_STATE_OPENED); - - // done func - impl->status.state = state; - if (func) ok = func((tb_aicp_http_ref_t)impl, state, &impl->status, priv); - } - // failed? - else - { - // init func and state - impl->clos_opening.func = func; - impl->clos_opening.priv = priv; - impl->clos_opening.state = state; - - // close it - ok = tb_aicp_http_clos((tb_aicp_http_ref_t)impl, tb_aicp_http_clos_opening_func, tb_null); - } - - // ok? - return ok; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_aicp_http_ref_t tb_aicp_http_init(tb_aicp_ref_t aicp) -{ - // check - tb_assert_and_check_return_val(aicp, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_aicp_http_impl_t* impl = tb_null; - do - { - // make impl - impl = tb_malloc0_type(tb_aicp_http_impl_t); - tb_assert_and_check_break(impl); - - // init state - impl->state = TB_STATE_CLOSED; - - // init stream - impl->stream = impl->sstream = tb_async_stream_init_sock(aicp); - tb_assert_and_check_break(impl->stream); - - // init head - impl->head = tb_hash_map_init(8, tb_element_str(tb_false), tb_element_str(tb_false)); - tb_assert_and_check_break(impl->head); - - // init cookies data - if (!tb_string_init(&impl->cookies)) break; - - // init line data - if (!tb_string_init(&impl->line_data)) break; - - // init cache data - if (!tb_buffer_init(&impl->cache_data)) break; - impl->cache_read = 0; - - // init option - if (!tb_http_option_init(&impl->option)) break; - - // init status - if (!tb_http_status_init(&impl->status)) break; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - if (impl) tb_aicp_http_exit((tb_aicp_http_ref_t)impl); - impl = tb_null; - } - - // ok? - return (tb_aicp_http_ref_t)impl; -} -tb_void_t tb_aicp_http_kill(tb_aicp_http_ref_t http) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return(impl); - - // kill it - tb_size_t state = tb_atomic_fetch_and_set(&impl->state, TB_STATE_KILLING); - tb_check_return(state != TB_STATE_KILLING); - - // trace - tb_trace_d("kill: .."); - - // kill transfer - if (impl->transfer) tb_async_transfer_kill(impl->transfer); - - // kill stream - if (impl->stream) tb_async_stream_kill(impl->stream); -} -tb_bool_t tb_aicp_http_exit(tb_aicp_http_ref_t http) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl, tb_false); - - // trace - tb_trace_d("exit: .."); - - // kill it first - tb_aicp_http_kill(http); - - // try closing it - tb_size_t tryn = 30; - tb_bool_t ok = tb_false; - while (!(ok = tb_aicp_http_clos_try(http)) && tryn--) - { - // wait some time - tb_msleep(200); - } - - // close failed? - if (!ok) - { - // trace - tb_trace_e("exit: %s: failed!", tb_url_cstr(&impl->option.url)); - return tb_false; - } - - // exit transfer - if (impl->transfer) tb_async_transfer_exit(impl->transfer); - impl->transfer = tb_null; - - // exit zstream - if (impl->zstream) tb_async_stream_exit(impl->zstream); - impl->zstream = tb_null; - - // exit cstream - if (impl->cstream) tb_async_stream_exit(impl->cstream); - impl->cstream = tb_null; - - // exit sstream - if (impl->sstream) tb_async_stream_exit(impl->sstream); - impl->sstream = tb_null; - - // exit stream - impl->stream = tb_null; - - // exit status - tb_http_status_exit(&impl->status); - - // exit option - tb_http_option_exit(&impl->option); - - // exit line data - tb_string_exit(&impl->line_data); - - // exit cache data - tb_buffer_exit(&impl->cache_data); - - // exit cookies data - tb_string_exit(&impl->cookies); - - // exit head - if (impl->head) tb_hash_map_exit(impl->head); - impl->head = tb_null; - - // free it - tb_free(impl); - - // trace - tb_trace_d("exit: ok"); - - // ok - return tb_true; -} -tb_bool_t tb_aicp_http_open(tb_aicp_http_ref_t http, tb_aicp_http_open_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && func, tb_false); - - // set opening - tb_size_t state = tb_atomic_fetch_and_pset(&impl->state, TB_STATE_CLOSED, TB_STATE_OPENING); - - // opened? done func directly - if (state == TB_STATE_OPENED) - { - impl->status.state = TB_STATE_OK; - func(http, impl->status.state, &impl->status, priv); - return tb_true; - } - - // must be closed - tb_assert_and_check_return_val(state == TB_STATE_CLOSED, tb_false); - - // init open - impl->func.open = func; - impl->priv = priv; - - // clear redirect - impl->redirect_tryn = 0; - - // done open - return tb_aicp_http_open_done(impl); -} -tb_bool_t tb_aicp_http_clos(tb_aicp_http_ref_t http, tb_aicp_http_clos_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && impl->stream && func, tb_false); - - // trace - tb_trace_d("clos: .."); - - // try closing ok? - if (tb_aicp_http_clos_try(http)) - { - // done func - func(http, TB_STATE_OK, priv); - return tb_true; - } - - // init func - impl->func.clos = func; - impl->priv = priv; - - // close transfer - if (impl->transfer) return tb_async_transfer_clos(impl->transfer, tb_aicp_http_clos_transfer_func, impl); - // close stream - else return tb_async_stream_clos(impl->stream, tb_aicp_http_clos_func, impl); -} -tb_bool_t tb_aicp_http_clos_try(tb_aicp_http_ref_t http) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && impl->stream, tb_false); - - // trace - tb_trace_d("clos: try: %s: ..", tb_url_cstr(&impl->option.url)); - - // done - tb_bool_t ok = tb_false; - do - { - // closed? - if (TB_STATE_CLOSED == tb_atomic_get(&impl->state)) - { - ok = tb_true; - break; - } - - // try closing transfer - if (impl->transfer && !tb_async_transfer_clos_try(impl->transfer)) break; - - // try closing it - if (!tb_async_stream_clos_try(impl->stream)) break; - - // clear it - tb_aicp_http_clos_clear(impl); - - // ok - ok = tb_true; - - } while (0); - - // trace - tb_trace_d("clos: try: %s: %s", tb_url_cstr(&impl->option.url), ok? "ok" : "no"); - - // ok? - return ok; -} -tb_bool_t tb_aicp_http_read(tb_aicp_http_ref_t http, tb_size_t size, tb_aicp_http_read_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && impl->stream && func, tb_false); - - // post read - return tb_aicp_http_read_after(http, 0, size, func, priv); -} -tb_bool_t tb_aicp_http_read_after(tb_aicp_http_ref_t http, tb_size_t delay, tb_size_t size, tb_aicp_http_read_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && impl->stream && func, tb_false); - - // check state - tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->state), tb_false); - - // read the cache data first, note: must be reentrant - tb_byte_t const* cache_data = tb_buffer_data(&impl->cache_data); - tb_size_t cache_size = tb_buffer_size(&impl->cache_data); - if (cache_data && cache_size && impl->cache_read < cache_size) - { - // read cache - impl->cache_read = cache_size; - - // update the content read - impl->content_read += cache_size; - - // done func - tb_bool_t ok = func(http, TB_STATE_OK, cache_data, cache_size, cache_size, priv); - - // clear cache data - tb_buffer_clear(&impl->cache_data); - impl->cache_read = 0; - - // break? - tb_check_return_val(ok, tb_true); - } - - // init read - impl->func.read = func; - impl->priv = priv; - - // post read - return tb_async_stream_read_after(impl->stream, delay, size, tb_aicp_http_read_func, impl); -} -tb_bool_t tb_aicp_http_seek(tb_aicp_http_ref_t http, tb_hize_t offset, tb_aicp_http_seek_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && impl->stream && func, tb_false); - - // set opening - tb_size_t state = tb_atomic_fetch_and_pset(&impl->state, TB_STATE_CLOSED, TB_STATE_OPENING); - - // killed? - tb_assert_and_check_return_val(state != TB_STATE_KILLING, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // trace - tb_trace_d("seek: %llu", offset); - - // init open - impl->func.open = tb_aicp_http_open_seek_func; - impl->priv = &impl->open_and.seek; - - // init open and seek - impl->open_and.seek.func = func; - impl->open_and.seek.priv = priv; - impl->open_and.seek.offset = offset; - - // clear redirect - impl->redirect_tryn = 0; - - // set range - impl->option.range.bof = offset; - impl->option.range.eof = impl->status.document_size > 0? impl->status.document_size - 1 : 0; - - // done open - if (!tb_aicp_http_open_done(impl)) break; - - // ok - ok = tb_true; - - } while (0); - - // ok? - return ok; -} -tb_bool_t tb_aicp_http_task(tb_aicp_http_ref_t http, tb_size_t delay, tb_aicp_http_task_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && impl->stream && func, tb_false); - - // check state - tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->state), tb_false); - - // init task - impl->func.task = func; - impl->priv = priv; - - // post task - return tb_async_stream_task(impl->stream, delay, tb_aicp_http_task_func, impl); -} -tb_bool_t tb_aicp_http_open_read(tb_aicp_http_ref_t http, tb_size_t size, tb_aicp_http_read_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && func, tb_false); - - // init open and read - impl->open_and.read.func = func; - impl->open_and.read.priv = priv; - impl->open_and.read.size = size; - return tb_aicp_http_open(http, tb_aicp_http_open_read_func, &impl->open_and.read); -} -tb_bool_t tb_aicp_http_open_seek(tb_aicp_http_ref_t http, tb_hize_t offset, tb_aicp_http_seek_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && func, tb_false); - - // open and seek - return tb_aicp_http_seek(http, offset, func, priv); -} -tb_aicp_ref_t tb_aicp_http_aicp(tb_aicp_http_ref_t http) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && impl->stream, tb_null); - - // the aicp - return tb_async_stream_aicp(impl->stream); -} -tb_bool_t tb_aicp_http_ctrl(tb_aicp_http_ref_t http, tb_size_t option, ...) -{ - // check - tb_aicp_http_impl_t* impl = (tb_aicp_http_impl_t*)http; - tb_assert_and_check_return_val(impl && impl->sstream && option, tb_false); - - // check - if (TB_HTTP_OPTION_CODE_IS_SET(option) && !tb_async_stream_is_closed(impl->sstream)) - { - // abort - tb_assert(0); - return tb_false; - } - - // init args - tb_va_list_t args; - tb_va_start(args, option); - - // done - tb_bool_t ok = tb_http_option_ctrl(&impl->option, option, args); - - // exit args - tb_va_end(args); - - // ok? - return ok; -} diff --git a/core/src/tbox/src/tbox/asio/deprecated/http.h b/core/src/tbox/src/tbox/asio/deprecated/http.h deleted file mode 100644 index 521f16199..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/http.h +++ /dev/null @@ -1,259 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file http.h - * @ingroup asio - * - */ -#ifndef TB_ASIO_HTTP_H -#define TB_ASIO_HTTP_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "aicp.h" -#include "../../network/http.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the aicp http ref type -typedef __tb_typeref__(aicp_http); - -/*! the aicp http open func type - * - * @param http the http handle - * @param state the state - * @param status the http status - * @param priv the func private data - * - * @return tb_true: ok, tb_false: error, but not break aicp - */ -typedef tb_bool_t (*tb_aicp_http_open_func_t)(tb_aicp_http_ref_t http, tb_size_t state, tb_http_status_t const* status, tb_cpointer_t priv); - -/*! the aicp http open func type - * - * @param http the http handle - * @param state the state - * @param priv the func private data - * - * @return tb_true: ok, tb_false: error, but not break aicp - */ -typedef tb_void_t (*tb_aicp_http_clos_func_t)(tb_aicp_http_ref_t http, tb_size_t state, tb_cpointer_t priv); - -/*! the aicp http read func type - * - * @param http the http handle - * @param state the state - * @param data the readed data - * @param real the real size, maybe zero - * @param size the need size - * @param priv the func private data - * - * @return tb_true: ok and continue it if need, tb_false: break it, but not break aicp - */ -typedef tb_bool_t (*tb_aicp_http_read_func_t)(tb_aicp_http_ref_t http, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv); - -/*! the aicp http seek func type - * - * @param http the http handle - * @param state the state - * @param offset the real offset - * @param priv the func private data - * - * @return tb_true: ok, tb_false: error, but not break aicp - */ -typedef tb_bool_t (*tb_aicp_http_seek_func_t)(tb_aicp_http_ref_t http, tb_size_t state, tb_hize_t offset, tb_cpointer_t priv); - -/*! the aicp http task func type - * - * @param http the http handle - * @param state the state - * @param priv the func private data - * - * @return tb_true: ok, tb_false: error, but not break aicp - */ -typedef tb_bool_t (*tb_aicp_http_task_func_t)(tb_aicp_http_ref_t http, tb_size_t state, tb_cpointer_t priv); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init the http - * - * @param aicp the aicp - * - * @return the http - */ -__tb_deprecated__ -tb_aicp_http_ref_t tb_aicp_http_init(tb_aicp_ref_t aicp); - -/*! kill the http - * - * @param http the http - */ -__tb_deprecated__ -tb_void_t tb_aicp_http_kill(tb_aicp_http_ref_t http); - -/*! exit the http - * - * @param http the http - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_exit(tb_aicp_http_ref_t http); - -/*! open the http - * - * @param http the http - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_open(tb_aicp_http_ref_t http, tb_aicp_http_open_func_t func, tb_cpointer_t priv); - -/*! close the http - * - * @param http the http - * @param func the func - * @param priv the private data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_clos(tb_aicp_http_ref_t http, tb_aicp_http_clos_func_t func, tb_cpointer_t priv); - -/*! try closing the http - * - * @param http the http - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_clos_try(tb_aicp_http_ref_t http); - -/*! read the http - * - * @param http the http - * @param size the read size, using the default size if be zero - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_read(tb_aicp_http_ref_t http, tb_size_t size, tb_aicp_http_read_func_t func, tb_cpointer_t priv); - -/*! read the http after the delay time - * - * @param http the http - * @param delay the delay time, ms - * @param size the read size, using the default size if be zero - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_read_after(tb_aicp_http_ref_t http, tb_size_t delay, tb_size_t size, tb_aicp_http_read_func_t func, tb_cpointer_t priv); - -/*! seek the http - * - * @param http the http - * @param offset the offset - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_seek(tb_aicp_http_ref_t http, tb_hize_t offset, tb_aicp_http_seek_func_t func, tb_cpointer_t priv); - -/*! task the http - * - * @param http the http - * @param delay the delay time, ms - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_task(tb_aicp_http_ref_t http, tb_size_t delay, tb_aicp_http_task_func_t func, tb_cpointer_t priv); - -/*! open and read the http, open it first if not opened - * - * @param http the http - * @param size the read size, using the default size if be zero - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_open_read(tb_aicp_http_ref_t http, tb_size_t size, tb_aicp_http_read_func_t func, tb_cpointer_t priv); - -/*! open and seek the http, open it first if not opened - * - * @param http the http - * @param offset the offset - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_open_seek(tb_aicp_http_ref_t http, tb_hize_t offset, tb_aicp_http_seek_func_t func, tb_cpointer_t priv); - -/*! the http aicp - * - * @param http the http - * - * @return the aicp - */ -__tb_deprecated__ -tb_aicp_ref_t tb_aicp_http_aicp(tb_aicp_http_ref_t http); - -/*! ctrl the http option - * - * @param http the http - * @param option the http option - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_http_ctrl(tb_aicp_http_ref_t http, tb_size_t option, ...); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/impl/aicp_aiop.c b/core/src/tbox/src/tbox/asio/deprecated/impl/aicp_aiop.c deleted file mode 100644 index 031f0d004..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/impl/aicp_aiop.c +++ /dev/null @@ -1,1795 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aicp.c - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the aiop ptor type -typedef struct __tb_aiop_ptor_impl_t -{ - // the ptor base - tb_aicp_ptor_impl_t base; - - // the wait aiop - tb_aiop_ref_t aiop; - - /* the aice spak - * - * index: 0: higher priority for conn, acpt and task - * index: 1: lower priority for io aice - */ - tb_queue_ref_t spak[2]; - - // the spak lock - tb_spinlock_t lock; - - // the spak wait - tb_semaphore_ref_t wait; - - // the spak loop - tb_thread_ref_t loop; - - // the aioe list - tb_aioe_ref_t list; - - // the aioe size - tb_size_t maxn; - - // the timer for task - tb_timer_ref_t timer; - - // the low precision timer for timeout - tb_ltimer_ref_t ltimer; - - // the private data for file - tb_handle_t fpriv; - - // the killing list lock - tb_spinlock_t klock; - - // the killing aico list - tb_vector_ref_t klist; - -}tb_aiop_ptor_impl_t; - -// the aiop aico type -typedef struct __tb_aiop_aico_t -{ - // the base - tb_aico_impl_t base; - - // the impl - tb_aiop_ptor_impl_t* impl; - - // the aioo - tb_aioo_ref_t aioo; - - // the aice - tb_aice_t aice; - - // the task - tb_handle_t task; - - /* wait ok? avoid spak double aice when wait killed/timeout and ok at same time - * need lock it using impl->lock - */ - tb_uint8_t wait_ok : 1; - - // is waiting? - tb_uint8_t waiting : 1; - - // is ltimer? - tb_uint8_t bltimer : 1; - -}tb_aiop_aico_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * file declaration - */ -static tb_bool_t tb_aicp_file_init(tb_aiop_ptor_impl_t* impl); -static tb_void_t tb_aicp_file_exit(tb_aiop_ptor_impl_t* impl); -static tb_bool_t tb_aicp_file_addo(tb_aiop_ptor_impl_t* impl, tb_aico_impl_t* aico); -static tb_void_t tb_aicp_file_kilo(tb_aiop_ptor_impl_t* impl, tb_aico_impl_t* aico); -static tb_bool_t tb_aicp_file_post(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice); -static tb_void_t tb_aicp_file_kill(tb_aiop_ptor_impl_t* impl); -static tb_void_t tb_aicp_file_poll(tb_aiop_ptor_impl_t* impl); -static tb_long_t tb_aicp_file_spak_read(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice); -static tb_long_t tb_aicp_file_spak_writ(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice); -static tb_long_t tb_aicp_file_spak_readv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice); -static tb_long_t tb_aicp_file_spak_writv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice); -static tb_long_t tb_aicp_file_spak_fsync(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * spak - */ -static __tb_inline__ tb_size_t tb_aiop_aioe_code(tb_aice_ref_t aice) -{ - // the aioe code - static tb_size_t s_code[] = - { - TB_AIOE_CODE_NONE - - , TB_AIOE_CODE_ACPT //< acpt - , TB_AIOE_CODE_CONN //< conn - , TB_AIOE_CODE_RECV //< recv - , TB_AIOE_CODE_SEND //< send - , TB_AIOE_CODE_RECV //< urecv - , TB_AIOE_CODE_SEND //< usend - , TB_AIOE_CODE_RECV //< recvv - , TB_AIOE_CODE_SEND //< sendv - , TB_AIOE_CODE_RECV //< urecvv - , TB_AIOE_CODE_SEND //< usendv - , TB_AIOE_CODE_SEND //< sendf - - , TB_AIOE_CODE_NONE - , TB_AIOE_CODE_NONE - , TB_AIOE_CODE_NONE - , TB_AIOE_CODE_NONE - , TB_AIOE_CODE_NONE - - , TB_AIOE_CODE_NONE - }; - tb_assert_and_check_return_val(aice->code && aice->code < tb_arrayn(s_code), TB_AIOE_CODE_NONE); - - // the aioe code - return s_code[aice->code]; -} -static tb_void_t tb_aiop_spak_work(tb_aiop_ptor_impl_t* impl) -{ - // check - tb_assert_and_check_return(impl && impl->wait && impl->base.aicp); - - // the worker size - tb_size_t work = tb_atomic_get(&impl->base.aicp->work); - - // the semaphore value - tb_long_t value = tb_semaphore_value(impl->wait); - - // post wait - if (value >= 0 && value < work) tb_semaphore_post(impl->wait, work - value); -} -static tb_bool_t tb_aiop_push_sock(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice && aice->aico, tb_false); - - // the priority - tb_size_t priority = tb_aice_impl_priority(aice); - tb_assert_and_check_return_val(priority < tb_arrayn(impl->spak) && impl->spak[priority], tb_false); - - // this aico is killed? post to higher priority queue - if (tb_aico_impl_is_killed((tb_aico_impl_t*)aice->aico)) priority = 0; - - // trace - tb_trace_d("push: aico: %p, handle: %p, code: %lu, priority: %lu", aice->aico, tb_aico_sock(aice->aico), aice->code, priority); - - // enter - tb_spinlock_enter(&impl->lock); - - // not full? - if (!tb_queue_full(impl->spak[priority])) - { - // push aice to the spak queue - tb_queue_put(impl->spak[priority], aice); - - // wait ok if be not acpt aice - if (aice->code != TB_AICE_CODE_ACPT) ((tb_aiop_aico_t*)aice->aico)->wait_ok = 1; - } - else - { - // trace - tb_trace_e("push: failed, the spak queue is full!"); - } - - // leave - tb_spinlock_leave(&impl->lock); - - // ok - return tb_true; -} -static tb_bool_t tb_aiop_push_acpt(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, tb_false); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_ACPT, tb_false); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, tb_false); - - // the priority - tb_size_t priority = tb_aice_impl_priority(aice); - tb_assert_and_check_return_val(priority < tb_arrayn(impl->spak) && impl->spak[priority], tb_false); - - // init the acpt aice - tb_aice_t acpt_aice = *aice; - acpt_aice.state = TB_STATE_OK; - - // done - tb_size_t list_indx = 0; - tb_size_t list_size = 0; - tb_socket_ref_t list_sock[2048]; - tb_ipaddr_t list_addr[2048]; - tb_size_t list_maxn = tb_arrayn(list_sock); - tb_socket_ref_t acpt = (tb_socket_ref_t)aico->base.handle; - tb_queue_ref_t spak = impl->spak[priority]; - tb_socket_ref_t sock = tb_null; - do - { - // accept it - for (list_size = 0; list_size < list_maxn && (list_sock[list_size] = tb_socket_accept(acpt, list_addr + list_size)); list_size++) ; - - // enter - tb_spinlock_enter(&impl->lock); - - // push some acpt aice - for (list_indx = 0; list_indx < list_size && (sock = list_sock[list_indx]); list_indx++) - { - // init aico - acpt_aice.u.acpt.aico = tb_aico_init(aico->base.aicp); - - // trace - tb_trace_d("push: acpt[%p]: sock: %p, aico: %p", aico->base.handle, sock, acpt_aice.u.acpt.aico); - - // open aico and push the acpt aice if not full? - if ( acpt_aice.u.acpt.aico - && tb_aico_open_sock(acpt_aice.u.acpt.aico, sock) - && !tb_queue_full(spak)) - { - // save addr - tb_ipaddr_copy(&acpt_aice.u.acpt.addr, list_addr + list_indx); - - // push to the spak queue - tb_queue_put(spak, &acpt_aice); - } - else - { - // close the left sock - tb_size_t i; - for (i = list_indx; i < list_size; i++) - { - // close it - if (list_sock[i]) tb_socket_exit(list_sock[i]); - list_sock[i] = tb_null; - } - - // exit aico - if (acpt_aice.u.acpt.aico) tb_aico_exit(acpt_aice.u.acpt.aico); - acpt_aice.u.acpt.aico = tb_null; - - // trace - tb_trace_e("push: acpt failed!"); - break; - } - } - - // leave - tb_spinlock_leave(&impl->lock); - - } while (list_indx == list_maxn); - - // ok - return tb_true; -} -static tb_int_t tb_aiop_spak_loop(tb_cpointer_t priv) -{ - // check - tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)priv; - tb_aicp_impl_t* aicp = impl? impl->base.aicp : tb_null; - - // done - do - { - // check - tb_assert_and_check_break(impl && impl->aiop && impl->list && impl->timer && impl->ltimer && aicp); - - // trace - tb_trace_d("loop: init"); - - // loop - while (!tb_atomic_get(&aicp->kill)) - { - // the delay - tb_size_t delay = tb_timer_delay(impl->timer); - - // the ldelay - tb_size_t ldelay = tb_ltimer_delay(impl->ltimer); - tb_assert_and_check_break(ldelay != -1); - - // trace - tb_trace_d("loop: wait: .."); - - // wait aioe - tb_long_t real = tb_aiop_wait(impl->aiop, impl->list, impl->maxn, tb_min(delay, ldelay)); - - // trace - tb_trace_d("loop: wait: %ld", real); - - // spak ctime - tb_cache_time_spak(); - - // spak timer - if (!tb_timer_spak(impl->timer)) break; - - // spak ltimer - if (!tb_ltimer_spak(impl->ltimer)) break; - - // killed? - tb_check_break(real >= 0); - - // error? out of range - tb_assert_and_check_break(real <= impl->maxn); - - // timeout? - tb_check_continue(real); - - // grow it if aioe is full - if (real == impl->maxn) - { - // grow size - impl->maxn += (aicp->maxn >> 4) + 16; - if (impl->maxn > aicp->maxn) impl->maxn = aicp->maxn; - - // grow list - impl->list = tb_ralloc(impl->list, impl->maxn * sizeof(tb_aioe_t)); - tb_assert_and_check_break(impl->list); - } - - // walk aioe list - tb_size_t i = 0; - tb_bool_t end = tb_false; - for (i = 0; i < real && !end; i++) - { - // the aioe - tb_aioe_ref_t aioe = &impl->list[i]; - tb_assert_and_check_break_state(aioe, end, tb_true); - - // the aice - tb_aice_ref_t aice = (tb_aice_ref_t)aioe->priv; - tb_assert_and_check_break_state(aice, end, tb_true); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_break_state(aico, end, tb_true); - - // have wait? - tb_check_continue(aice->code); - - // have been waited ok for the timer timeout/killed func? need not spak it repeatly - tb_check_continue(!aico->wait_ok); - - // sock? - if (aico->base.type == TB_AICO_TYPE_SOCK) - { - // push the acpt aice - if (aice->code == TB_AICE_CODE_ACPT) end = tb_aiop_push_acpt(impl, aice)? tb_false : tb_true; - // push the sock aice - else end = tb_aiop_push_sock(impl, aice)? tb_false : tb_true; - } - else if (aico->base.type == TB_AICO_TYPE_FILE) - { - // poll file - tb_aicp_file_poll(impl); - } - else tb_assert(0); - } - - // end? - tb_check_break(!end); - - // work it - tb_aiop_spak_work(impl); - } - - } while (0); - - // trace - tb_trace_d("loop: exit"); - - // kill - tb_aicp_kill((tb_aicp_ref_t)aicp); - - // exit - return 0; -} -static tb_void_t tb_aiop_spak_wait_timeout(tb_bool_t killed, tb_cpointer_t priv) -{ - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)priv; - tb_assert_and_check_return(aico && aico->waiting); - - // the impl - tb_aiop_ptor_impl_t* impl = aico->impl; - tb_assert_and_check_return(impl && impl->aiop); - - // for sock - if (aico->base.type == TB_AICO_TYPE_SOCK) - { - // check - tb_assert_and_check_return(aico->aioo); - - // delo aioo - tb_aiop_delo(impl->aiop, aico->aioo); - aico->aioo = tb_null; - } - - // have been waited ok for the spak loop? need not spak it repeatly - tb_bool_t ok = tb_false; - if (!aico->wait_ok) - { - // the priority - tb_size_t priority = tb_aice_impl_priority(&aico->aice); - tb_assert_and_check_return(priority < tb_arrayn(impl->spak) && impl->spak[priority]); - - // trace - tb_trace_d("wait: timeout: code: %lu, priority: %lu, time: %lld", aico->aice.code, priority, tb_cache_time_mclock()); - - // enter - tb_spinlock_enter(&impl->lock); - - // spak aice - if (!tb_queue_full(impl->spak[priority])) - { - // save state - aico->aice.state = killed? TB_STATE_KILLED : TB_STATE_TIMEOUT; - - // put it - tb_queue_put(impl->spak[priority], &aico->aice); - - // ok - ok = tb_true; - aico->wait_ok = 1; - } - else tb_assert(0); - - // leave - tb_spinlock_leave(&impl->lock); - } - - // work it - if (ok) tb_aiop_spak_work(impl); -} -static tb_bool_t tb_aiop_spak_wait(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && impl->aiop && impl->ltimer && aice, tb_false); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle && !aico->task, tb_false); - - // the aioe code - tb_size_t code = tb_aiop_aioe_code(aice); - tb_assert_and_check_return_val(code != TB_AIOE_CODE_NONE, tb_false); - - // trace - tb_trace_d("wait: aico: %p, code: %lu: time: %lld: ..", aico, aice->code, tb_cache_time_mclock()); - - // done - tb_bool_t ok = tb_false; - tb_aice_t prev = aico->aice; - do - { - // wait it - aico->aice = *aice; - aico->waiting = 1; - aico->wait_ok = 0; - - // wait once if not accept - if (aice->code != TB_AICE_CODE_ACPT) code |= TB_AIOE_CODE_ONESHOT; - - // using the edge triggered mode - if (tb_aiop_have(impl->aiop, TB_AIOE_CODE_CLEAR)) - code |= TB_AIOE_CODE_CLEAR; - - // have aioo? - if (!aico->aioo) - { - // addo wait - if (!(aico->aioo = tb_aiop_addo(impl->aiop, aico->base.handle, code, &aico->aice))) break; - } - else - { - // sete wait - if (!tb_aiop_sete(impl->aiop, aico->aioo, code, &aico->aice)) break; - } - - // add timeout task - tb_long_t timeout = tb_aico_impl_timeout_from_code((tb_aico_impl_t*)aico, aice->code); - if (timeout >= 0) - { - // add it - aico->task = tb_ltimer_task_init(impl->ltimer, timeout, tb_false, tb_aiop_spak_wait_timeout, aico); - tb_assert_and_check_break(aico->task); - aico->bltimer = 1; - } - - // ok - ok = tb_true; - - } while (0); - - // failed? restore it - if (!ok) - { - // trace - tb_trace_d("wait: aico: %p, code: %lu: failed", aico, aice->code); - - // restore it - aico->aice = prev; - aico->waiting = 0; - } - - // ok? - return ok; -} -static tb_long_t tb_aiop_spak_acpt(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_ACPT, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - tb_assert_and_check_return_val(!aico->waiting, -1); - - // trace - tb_trace_d("acpt[%p]: wait: ..", aico); - - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - - // trace - tb_trace_d("acpt[%p]: wait: failed", aico); - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_conn(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_CONN, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // check address - tb_assert(!tb_ipaddr_is_empty(&aice->u.conn.addr)); - - // try to connect it - tb_long_t ok = tb_socket_connect(aico->base.handle, &aice->u.conn.addr); - - // trace - tb_trace_d("conn[%p]: %{ipaddr}: %ld", aico, &aice->u.conn.addr, ok); - - // no connected? wait it - if (!ok) - { - // wait it - if (!aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed - else aice->state = TB_STATE_FAILED; - } - - // save it - aice->state = ok > 0? TB_STATE_OK : TB_STATE_FAILED; - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_recv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_RECV, -1); - tb_assert_and_check_return_val(aice->u.recv.data && aice->u.recv.size, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // try to recv it - tb_size_t recv = 0; - tb_long_t real = 0; - while (recv < aice->u.recv.size) - { - // recv it - real = tb_socket_recv(aico->base.handle, aice->u.recv.data + recv, aice->u.recv.size - recv); - - // save recv - if (real > 0) recv += real; - else break; - } - - // trace - tb_trace_d("recv[%p]: %lu", aico, recv); - - // no recv? - if (!recv) - { - // wait it - if (!real && !aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed - else aice->state = TB_STATE_CLOSED; - } - else - { - // ok or closed? - aice->state = TB_STATE_OK; - - // save the recv size - aice->u.recv.real = recv; - } - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_send(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_SEND, -1); - tb_assert_and_check_return_val(aice->u.send.data && aice->u.send.size, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // try to send it - tb_size_t send = 0; - tb_long_t real = 0; - while (send < aice->u.send.size) - { - // send it - real = tb_socket_send(aico->base.handle, aice->u.send.data + send, aice->u.send.size - send); - - // save send - if (real > 0) send += real; - else break; - } - - // trace - tb_trace_d("send[%p]: %lu", aico, send); - - // no send? - if (!send) - { - // wait it - if (!real && !aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed - else aice->state = TB_STATE_CLOSED; - } - else - { - // ok or closed? - aice->state = TB_STATE_OK; - - // save the send size - aice->u.send.real = send; - } - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_urecv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_URECV, -1); - tb_assert_and_check_return_val(aice->u.urecv.data && aice->u.urecv.size, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // try to recv it - tb_size_t recv = 0; - tb_long_t real = 0; - while (recv < aice->u.urecv.size) - { - // recv it - real = tb_socket_urecv(aico->base.handle, &aice->u.urecv.addr, aice->u.urecv.data + recv, aice->u.urecv.size - recv); - - // save recv - if (real > 0) recv += real; - else break; - } - - // no recv? - if (!recv) - { - // wait it - if (!real && !aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed - else aice->state = TB_STATE_CLOSED; - } - else - { - // trace - tb_trace_d("urecv[%p]: %{ipaddr}: %lu", aico, &aice->u.urecv.addr, recv); - - // ok or closed? - aice->state = TB_STATE_OK; - - // save the recv size - aice->u.urecv.real = recv; - } - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_usend(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_USEND, -1); - tb_assert_and_check_return_val(aice->u.usend.data && aice->u.usend.size, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // try to send it - tb_size_t send = 0; - tb_long_t real = 0; - while (send < aice->u.usend.size) - { - // send it - real = tb_socket_usend(aico->base.handle, &aice->u.usend.addr, aice->u.usend.data + send, aice->u.usend.size - send); - - // save send - if (real > 0) send += real; - else break; - } - - // trace - tb_trace_d("usend[%p]: %{ipaddr}: %lu", aico, &aice->u.usend.addr, send); - - // no send? - if (!send) - { - // wait it - if (!real && !aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed - else aice->state = TB_STATE_CLOSED; - } - else - { - // ok or closed? - aice->state = TB_STATE_OK; - - // save the send size - aice->u.usend.real = send; - } - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_recvv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_RECVV, -1); - tb_assert_and_check_return_val(aice->u.recvv.list && aice->u.recvv.size, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // recv it - tb_long_t real = tb_socket_recvv(aico->base.handle, aice->u.recvv.list, aice->u.recvv.size); - - // trace - tb_trace_d("recvv[%p]: %lu", aico, real); - - // ok? - if (real > 0) - { - aice->u.recvv.real = real; - aice->state = TB_STATE_OK; - } - // no recv? - else if (!real && !aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed? - else aice->state = TB_STATE_CLOSED; - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_sendv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_SENDV, -1); - tb_assert_and_check_return_val(aice->u.sendv.list && aice->u.sendv.size, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // send it - tb_long_t real = tb_socket_sendv(aico->base.handle, aice->u.sendv.list, aice->u.sendv.size); - - // trace - tb_trace_d("sendv[%p]: %lu", aico, real); - - // ok? - if (real > 0) - { - aice->u.sendv.real = real; - aice->state = TB_STATE_OK; - } - // no send? - else if (!real && !aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed? - else aice->state = TB_STATE_CLOSED; - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_urecvv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_URECVV, -1); - tb_assert_and_check_return_val(aice->u.urecvv.list && aice->u.urecvv.size, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // recv it - tb_long_t real = tb_socket_urecvv(aico->base.handle, &aice->u.urecvv.addr, aice->u.urecvv.list, aice->u.urecvv.size); - - // trace - tb_trace_d("urecvv[%p]: %{ipaddr}: %lu", aico, &aice->u.urecvv.addr, real); - - // ok? - if (real > 0) - { - aice->u.urecvv.real = real; - aice->state = TB_STATE_OK; - } - // no recv? - else if (!real && !aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed? - else aice->state = TB_STATE_CLOSED; - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_usendv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_USENDV, -1); - tb_assert_and_check_return_val(aice->u.usendv.list && aice->u.usendv.size, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // send it - tb_long_t real = tb_socket_usendv(aico->base.handle, &aice->u.usendv.addr, aice->u.usendv.list, aice->u.usendv.size); - - // trace - tb_trace_d("usendv[%p]: %{ipaddr}: %lu", aico, &aice->u.usendv.addr, real); - - // ok? - if (real > 0) - { - aice->u.usendv.real = real; - aice->state = TB_STATE_OK; - } - // no send? - else if (!real && !aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed? - else aice->state = TB_STATE_CLOSED; - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_long_t tb_aiop_spak_sendf(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_SENDF, -1); - tb_assert_and_check_return_val(aice->u.sendf.file && aice->u.sendf.size, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && aico->base.handle, -1); - - // try to send it - tb_long_t real = 0; - tb_hize_t send = 0; - tb_hize_t seek = aice->u.sendf.seek; - tb_hize_t size = aice->u.sendf.size; - tb_handle_t file = aice->u.sendf.file; - while (send < size) - { - // send it - real = tb_socket_sendf(aico->base.handle, file, seek + send, size - send); - - // save send - if (real > 0) send += real; - else break; - } - - // trace - tb_trace_d("sendf[%p]: %llu", aico, send); - - // no send? - if (!send) - { - // wait it - if (!real && !aico->waiting) - { - // wait ok? - if (tb_aiop_spak_wait(impl, aice)) return 0; - // wait failed - else aice->state = TB_STATE_FAILED; - } - // closed - else aice->state = TB_STATE_CLOSED; - } - else - { - // ok or closed? - aice->state = TB_STATE_OK; - - // save the send size - aice->u.sendf.real = send; - } - - // reset wait - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // ok - return 1; -} -static tb_void_t tb_aiop_spak_runtask_timeout(tb_bool_t killed, tb_cpointer_t priv) -{ - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)priv; - tb_assert_and_check_return(aico && aico->waiting); - - // the impl - tb_aiop_ptor_impl_t* impl = aico->impl; - tb_assert_and_check_return(impl); - - // the priority - tb_size_t priority = tb_aice_impl_priority(&aico->aice); - tb_assert_and_check_return(priority < tb_arrayn(impl->spak) && impl->spak[priority]); - - // enter - tb_spinlock_enter(&impl->lock); - - // trace - tb_trace_d("runtask: timeout: code: %lu, priority: %lu, size: %lu", aico->aice.code, priority, tb_queue_size(impl->spak[priority])); - - // spak aice - tb_bool_t ok = tb_false; - if (!tb_queue_full(impl->spak[priority])) - { - // save state - aico->aice.state = killed? TB_STATE_KILLED : TB_STATE_OK; - - // put it - tb_queue_put(impl->spak[priority], &aico->aice); - - // ok - ok = tb_true; - } - else tb_assert(0); - - // leave - tb_spinlock_leave(&impl->lock); - - // work it - if (ok) tb_aiop_spak_work(impl); -} -static tb_long_t tb_aiop_spak_runtask(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && impl->aiop && impl->ltimer && impl->timer && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_RUNTASK, -1); - tb_assert_and_check_return_val(aice->u.runtask.when, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico && !aico->task, -1); - - // now - tb_hong_t now = tb_cache_time_mclock(); - - // timeout? - tb_long_t ok = -1; - if (aice->u.runtask.when <= now) - { - // trace - tb_trace_d("runtask: when: %llu, now: %lld: ok", aice->u.runtask.when, now); - - // ok - aice->state = TB_STATE_OK; - ok = 1; - } - else - { - // trace - tb_trace_d("runtask: when: %llu, now: %lld: ..", aice->u.runtask.when, now); - - // wait it - aico->aice = *aice; - aico->waiting = 1; - - // add timeout task, is the higher precision timer? - if (aico->base.handle) - { - // the top when - tb_hize_t top = tb_timer_top(impl->timer); - - // add task - aico->task = tb_timer_task_init_at(impl->timer, aice->u.runtask.when, 0, tb_false, tb_aiop_spak_runtask_timeout, aico); - aico->bltimer = 0; - - // the top task is changed? spak aiop - if (aico->task && aice->u.runtask.when < top) - tb_aiop_spak(impl->aiop); - } - else - { - aico->task = tb_ltimer_task_init_at(impl->ltimer, aice->u.runtask.when, 0, tb_false, tb_aiop_spak_runtask_timeout, aico); - aico->bltimer = 1; - } - - // wait - ok = 0; - } - - // ok - return ok; -} -static tb_long_t tb_aiop_spak_clos(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && impl->aiop && impl->ltimer && impl->timer && aice, -1); - tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_CLOS, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico, -1); - - // trace - tb_trace_d("clos: aico: %p, code: %u: %s", aico, aice->code, tb_state_cstr(tb_atomic_get(&aico->base.state))); - - // exit the timer task - if (aico->task) - { - if (aico->bltimer) tb_ltimer_task_exit(impl->ltimer, aico->task); - else tb_timer_task_exit(impl->timer, aico->task); - aico->bltimer = 0; - } - aico->task = tb_null; - - // exit the sock - if (aico->base.type == TB_AICO_TYPE_SOCK) - { - // remove aioo - if (aico->aioo) tb_aiop_delo(impl->aiop, aico->aioo); - aico->aioo = tb_null; - - // close the socket handle - if (aico->base.handle) tb_socket_exit((tb_socket_ref_t)aico->base.handle); - aico->base.handle = tb_null; - } - // exit file - else if (aico->base.type == TB_AICO_TYPE_FILE) - { - // exit the file handle - if (aico->base.handle) tb_file_exit((tb_file_ref_t)aico->base.handle); - aico->base.handle = tb_null; - } - - // clear waiting state - aico->waiting = 0; - aico->wait_ok = 0; - aico->aice.code = TB_AICE_CODE_NONE; - - // clear type - aico->base.type = TB_AICO_TYPE_NONE; - - // clear timeout - tb_size_t i = 0; - tb_size_t n = tb_arrayn(aico->base.timeout); - for (i = 0; i < n; i++) aico->base.timeout[i] = -1; - - // closed - tb_atomic_set(&aico->base.state, TB_STATE_CLOSED); - - // ok - aice->state = TB_STATE_OK; - return 1; -} -static tb_long_t tb_aiop_spak_done(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && impl->timer && impl->ltimer && aice, -1); - - // the aico - tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; - tb_assert_and_check_return_val(aico, -1); - - // remove task - if (aico->task) - { - if (aico->bltimer) tb_ltimer_task_exit(impl->ltimer, aico->task); - else tb_timer_task_exit(impl->timer, aico->task); - aico->bltimer = 0; - } - aico->task = tb_null; - - // spak the killed aice if not closing - if (tb_aico_impl_is_killed(&aico->base) && aice->code != TB_AICE_CODE_CLOS) - { - // clear waiting state if not accept - if (aice->code != TB_AICE_CODE_ACPT) - { - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - } - - // save state - aice->state = TB_STATE_KILLED; - - // trace - tb_trace_d("spak: aico: %p, code: %u: killed", aico, aice->code); - - // ok - return 1; - } - - // no pending? spak it directly - if (aice->state != TB_STATE_PENDING) - { - // clear waiting state if not accept - if (aice->code != TB_AICE_CODE_ACPT) - { - aico->waiting = 0; - aico->aice.code = TB_AICE_CODE_NONE; - } - - // ok - return 1; - } - - // init spak - static tb_long_t (*s_spak[])(tb_aiop_ptor_impl_t* , tb_aice_ref_t) = - { - tb_null - - , tb_aiop_spak_acpt - , tb_aiop_spak_conn - , tb_aiop_spak_recv - , tb_aiop_spak_send - , tb_aiop_spak_urecv - , tb_aiop_spak_usend - , tb_aiop_spak_recvv - , tb_aiop_spak_sendv - , tb_aiop_spak_urecvv - , tb_aiop_spak_usendv - , tb_aiop_spak_sendf - - , tb_aicp_file_spak_read - , tb_aicp_file_spak_writ - , tb_aicp_file_spak_readv - , tb_aicp_file_spak_writv - , tb_aicp_file_spak_fsync - - , tb_aiop_spak_runtask - , tb_null - }; - tb_assert_and_check_return_val(aice->code && aice->code < tb_arrayn(s_spak) && s_spak[aice->code], -1); - - // done spak - return s_spak[aice->code](impl, aice); -} -static tb_void_t tb_aiop_spak_klist(tb_aiop_ptor_impl_t* impl) -{ - // check - tb_assert_and_check_return(impl && impl->klist); - - // enter - tb_spinlock_enter(&impl->klock); - - // kill it if exists the killing aico - if (tb_vector_size(impl->klist)) - { - // kill all - tb_for_all_if (tb_aico_impl_t*, aico, impl->klist, aico) - { - // the aiop aico - tb_aiop_aico_t* aiop_aico = (tb_aiop_aico_t*)aico; - - // sock? - if (aico->type == TB_AICO_TYPE_SOCK) - { - // add it first if do not exists timeout task - if (!aiop_aico->task) - { - aiop_aico->task = tb_ltimer_task_init(impl->ltimer, 10000, tb_false, tb_aiop_spak_wait_timeout, aico); - aiop_aico->bltimer = 1; - } - - // kill the task - if (aiop_aico->task) - { - // kill task - if (aiop_aico->bltimer) tb_ltimer_task_kill(impl->ltimer, aiop_aico->task); - else tb_timer_task_kill(impl->timer, aiop_aico->task); - } - } - else if (aico->type == TB_AICO_TYPE_FILE) - { - // kill file - tb_aicp_file_kilo(impl, aico); - } - - // trace - tb_trace_d("kill: aico: %p, type: %u: ok", aico, aico->type); - } - } - - // clear the killing aico list - tb_vector_clear(impl->klist); - - // leave - tb_spinlock_leave(&impl->klock); - - /* the aiop will wait long time if the lastest task wait period is too long - * so spak the aiop manually for spak the timer - */ - tb_aiop_spak(impl->aiop); -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_bool_t tb_aiop_ptor_addo(tb_aicp_ptor_impl_t* ptor, tb_aico_impl_t* aico) -{ - // check - tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; - tb_assert_and_check_return_val(impl && impl->aiop && aico, tb_false); - - // the aiop aico - tb_aiop_aico_t* aiop_aico = (tb_aiop_aico_t*)aico; - - // init impl - aiop_aico->impl = impl; - - // done - tb_bool_t ok = tb_false; - switch (aico->type) - { - case TB_AICO_TYPE_SOCK: - { - // check - tb_assert_and_check_break(aico->handle); - - // ok - ok = tb_true; - } - break; - case TB_AICO_TYPE_FILE: - { - // check - tb_assert_and_check_break(aico->handle); - - // file: addo - ok = tb_aicp_file_addo(impl, aico); - } - break; - case TB_AICO_TYPE_TASK: - { - // ok - ok = tb_true; - } - break; - default: - break; - } - - // ok? - return ok; -} -static tb_void_t tb_aiop_ptor_kilo(tb_aicp_ptor_impl_t* ptor, tb_aico_impl_t* aico) -{ - // check - tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; - tb_assert_and_check_return(impl && impl->klist && aico); - - // trace - tb_trace_d("kill: aico: %p, type: %u: ..", aico, aico->type); - - // append the killing aico - tb_spinlock_enter(&impl->klock); - tb_vector_insert_tail(impl->klist, aico); - tb_spinlock_leave(&impl->klock); - - // work it - tb_aiop_spak_work(impl); -} -static tb_bool_t tb_aiop_ptor_post(tb_aicp_ptor_impl_t* ptor, tb_aice_ref_t aice) -{ - // check - tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; - tb_assert_and_check_return_val(impl && aice && aice->aico, tb_false); - - // optimizate to spak the clos aice - if (aice->code == TB_AICE_CODE_CLOS) - { - // spak the clos - tb_aice_t resp = *aice; - if (tb_aiop_spak_clos(impl, &resp) <= 0) return tb_false; - - // done the aice response function - aice->func(&resp); - - // post ok - return tb_true; - } - - // the priority - tb_size_t priority = tb_aice_impl_priority(aice); - tb_assert_and_check_return_val(priority < tb_arrayn(impl->spak) && impl->spak[priority], tb_false); - - // done - tb_bool_t ok = tb_true; - tb_aico_impl_t* aico = (tb_aico_impl_t*)aice->aico; - switch (aico->type) - { - case TB_AICO_TYPE_SOCK: - case TB_AICO_TYPE_TASK: - { - // enter - tb_spinlock_enter(&impl->lock); - - // post aice - if (!tb_queue_full(impl->spak[priority])) - { - // put - tb_queue_put(impl->spak[priority], aice); - - // trace - tb_trace_d("post: code: %lu, priority: %lu, size: %lu", aice->code, priority, tb_queue_size(impl->spak[priority])); - } - else - { - // failed - ok = tb_false; - - // trace - tb_trace_e("post: code: %lu, priority: %lu, size: %lu: failed", aice->code, priority, tb_queue_size(impl->spak[priority])); - } - - // leave - tb_spinlock_leave(&impl->lock); - } - break; - case TB_AICO_TYPE_FILE: - { - // post file - ok = tb_aicp_file_post(impl, aice); - } - break; - default: - ok = tb_false; - break; - } - - // work it - if (ok) tb_aiop_spak_work(impl); - - // ok? - return ok; -} -static tb_void_t tb_aiop_ptor_kill(tb_aicp_ptor_impl_t* ptor) -{ - // check - tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; - tb_assert_and_check_return(impl && impl->timer && impl->ltimer && impl->aiop); - - // trace - tb_trace_d("kill: .."); - - // kill aiop - tb_aiop_kill(impl->aiop); - - // kill file - tb_aicp_file_kill(impl); - - // work it - tb_aiop_spak_work(impl); -} -static tb_void_t tb_aiop_ptor_exit(tb_aicp_ptor_impl_t* ptor) -{ - // check - tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; - tb_assert_and_check_return(impl); - - // trace - tb_trace_d("exit"); - - // exit file - tb_aicp_file_exit(impl); - - // exit loop - if (impl->loop) - { - tb_long_t wait = 0; - if ((wait = tb_thread_wait(impl->loop, 5000, tb_null)) <= 0) - { - // trace - tb_trace_e("loop[%p]: wait failed: %ld!", impl->loop, wait); - } - tb_thread_exit(impl->loop); - impl->loop = tb_null; - } - - // exit spak - tb_spinlock_enter(&impl->lock); - if (impl->spak[0]) tb_queue_exit(impl->spak[0]); - if (impl->spak[1]) tb_queue_exit(impl->spak[1]); - impl->spak[0] = tb_null; - impl->spak[1] = tb_null; - tb_spinlock_leave(&impl->lock); - - // exit kill - tb_spinlock_enter(&impl->klock); - if (impl->klist) tb_vector_exit(impl->klist); - impl->klist = tb_null; - tb_spinlock_leave(&impl->klock); - - // exit aiop - if (impl->aiop) tb_aiop_exit(impl->aiop); - impl->aiop = tb_null; - - // exit list - if (impl->list) tb_free(impl->list); - impl->list = tb_null; - - // exit wait - if (impl->wait) tb_semaphore_exit(impl->wait); - impl->wait = tb_null; - - // exit timer - if (impl->timer) tb_timer_exit(impl->timer); - impl->timer = tb_null; - - // exit ltimer - if (impl->ltimer) tb_ltimer_exit(impl->ltimer); - impl->ltimer = tb_null; - - // exit lock - tb_spinlock_exit(&impl->lock); - - // exit it - tb_free(impl); -} -static tb_long_t tb_aiop_ptor_spak(tb_aicp_ptor_impl_t* ptor, tb_handle_t loop, tb_aice_ref_t resp, tb_long_t timeout) -{ - // check - tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; - tb_aicp_impl_t* aicp = impl? impl->base.aicp : tb_null; - tb_assert_and_check_return_val(impl && impl->wait && aicp && resp, -1); - - // spak the killing list - tb_aiop_spak_klist(impl); - - // enter - tb_spinlock_enter(&impl->lock); - - // done - tb_long_t ok = -1; - tb_bool_t null = tb_false; - do - { - // check - tb_assert_and_check_break(impl->spak[0] && impl->spak[1]); - - // clear ok - ok = 0; - - // spak aice from the higher priority spak first - if (!(null = tb_queue_null(impl->spak[0]))) - { - // get resp - tb_aice_ref_t aice = tb_queue_get(impl->spak[0]); - if (aice) - { - // save resp - *resp = *aice; - - // trace - tb_trace_d("spak[%u]: code: %lu, priority: 0, size: %lu", (tb_uint16_t)tb_thread_self(), aice->code, tb_queue_size(impl->spak[0])); - - // pop it - tb_queue_pop(impl->spak[0]); - - // ok - ok = 1; - } - } - - // no aice? spak aice from the lower priority spak next - if (!ok && !(null = tb_queue_null(impl->spak[1]))) - { - // get resp - tb_aice_ref_t aice = tb_queue_get(impl->spak[1]); - if (aice) - { - // save resp - *resp = *aice; - - // trace - tb_trace_d("spak[%u]: code: %lu, priority: 1, size: %lu", (tb_uint16_t)tb_thread_self(), aice->code, tb_queue_size(impl->spak[1])); - - // pop it - tb_queue_pop(impl->spak[1]); - - // ok - ok = 1; - } - } - - } while (0); - - // leave - tb_spinlock_leave(&impl->lock); - - // done it - if (ok) ok = tb_aiop_spak_done(impl, resp); - - // null? wait it - tb_check_return_val(!ok && null, ok); - - // killed? break it - tb_check_return_val(!tb_atomic_get(&aicp->kill), -1); - - // trace - tb_trace_d("wait[%u]: ..", (tb_uint16_t)tb_thread_self()); - - // wait some time - if (tb_semaphore_wait(impl->wait, timeout) < 0) return -1; - - // timeout - return 0; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * file implementation - */ -#include "aicp_file.c" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -static tb_aicp_ptor_impl_t* tb_aiop_ptor_init(tb_aicp_impl_t* aicp) -{ - // check - tb_assert_and_check_return_val(aicp && aicp->maxn, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_aiop_ptor_impl_t* impl = tb_null; - do - { - // make ptor - impl = tb_malloc0_type(tb_aiop_ptor_impl_t); - tb_assert_and_check_break(impl); - - // init base - impl->base.aicp = aicp; - impl->base.step = sizeof(tb_aiop_aico_t); - impl->base.kill = tb_aiop_ptor_kill; - impl->base.exit = tb_aiop_ptor_exit; - impl->base.addo = tb_aiop_ptor_addo; - impl->base.kilo = tb_aiop_ptor_kilo; - impl->base.post = tb_aiop_ptor_post; - impl->base.loop_spak = tb_aiop_ptor_spak; - - // init lock - if (!tb_spinlock_init(&impl->lock)) break; - - // init wait - impl->wait = tb_semaphore_init(0); - tb_assert_and_check_break(impl->wait); - - // init aiop - impl->aiop = tb_aiop_init(aicp->maxn); - tb_assert_and_check_break(impl->aiop); - - // check - tb_assert_and_check_break(tb_aiop_have(impl->aiop, TB_AIOE_CODE_EALL | TB_AIOE_CODE_ONESHOT)); - - // init spak - impl->spak[0] = tb_queue_init((aicp->maxn >> 4) + 16, tb_element_mem(sizeof(tb_aice_t), tb_null, tb_null)); - impl->spak[1] = tb_queue_init((aicp->maxn >> 4) + 16, tb_element_mem(sizeof(tb_aice_t), tb_null, tb_null)); - tb_assert_and_check_break(impl->spak[0] && impl->spak[1]); - - // init file - if (!tb_aicp_file_init(impl)) break; - - // init list - impl->maxn = (aicp->maxn >> 4) + 16; - impl->list = tb_nalloc0(impl->maxn, sizeof(tb_aioe_t)); - tb_assert_and_check_break(impl->list); - - // init timer and using cache time - impl->timer = tb_timer_init(aicp->maxn >> 8, tb_true); - tb_assert_and_check_break(impl->timer); - - // init ltimer and using cache time - impl->ltimer = tb_ltimer_init(aicp->maxn >> 8, TB_LTIMER_TICK_S, tb_true); - tb_assert_and_check_break(impl->ltimer); - - // init the killing list lock - if (!tb_spinlock_init(&impl->klock)) break; - - // init the killing aico list - impl->klist = tb_vector_init((aicp->maxn >> 6) + 16, tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_break(impl->klist); - - // register lock profiler -#ifdef TB_LOCK_PROFILER_ENABLE - tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&impl->lock, "aicp_aiop"); -#endif - - // init loop - impl->loop = tb_thread_init(tb_null, tb_aiop_spak_loop, impl, 0); - tb_assert_and_check_break(impl->loop); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (impl) tb_aiop_ptor_exit((tb_aicp_ptor_impl_t*)impl); - return tb_null; - } - - // ok? - return (tb_aicp_ptor_impl_t*)impl; -} - diff --git a/core/src/tbox/src/tbox/asio/deprecated/impl/aicp_file.c b/core/src/tbox/src/tbox/asio/deprecated/impl/aicp_file.c deleted file mode 100644 index c8c60df5f..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/impl/aicp_file.c +++ /dev/null @@ -1,238 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file aicp_file.c - * @ingroup platform - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_bool_t tb_aicp_file_init(tb_aiop_ptor_impl_t* impl) -{ - return tb_true; -} -static tb_void_t tb_aicp_file_exit(tb_aiop_ptor_impl_t* impl) -{ -} -static tb_bool_t tb_aicp_file_addo(tb_aiop_ptor_impl_t* impl, tb_aico_impl_t* aico) -{ - return tb_true; -} -static tb_void_t tb_aicp_file_kilo(tb_aiop_ptor_impl_t* impl, tb_aico_impl_t* aico) -{ - // check - tb_file_ref_t file = tb_aico_file((tb_aico_ref_t)aico); - tb_assert_and_check_return(file); - - // kill it - tb_file_exit(file); -} -static tb_bool_t tb_aicp_file_post(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice, tb_false); - - // the priority - tb_size_t priority = tb_aice_impl_priority(aice); - tb_assert_and_check_return_val(priority < tb_arrayn(impl->spak) && impl->spak[priority], tb_false); - - // enter - tb_spinlock_enter(&impl->lock); - - // post aice - tb_bool_t ok = tb_true; - if (!tb_queue_full(impl->spak[priority])) - { - // put - tb_queue_put(impl->spak[priority], aice); - - // trace - tb_trace_d("post: code: %lu, priority: %lu, size: %lu", aice->code, priority, tb_queue_size(impl->spak[priority])); - } - else - { - // failed - ok = tb_false; - - // assert - tb_assert(0); - } - - // leave - tb_spinlock_leave(&impl->lock); - - // ok? - return ok; -} -static tb_long_t tb_aicp_file_spak_read(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice && aice->code == TB_AICE_CODE_READ, -1); - tb_assert_and_check_return_val(aice->u.read.data && aice->u.read.size, -1); - - // the file - tb_file_ref_t file = tb_aico_file(aice->aico); - tb_assert_and_check_return_val(file, -1); - - // read it from the given offset - tb_long_t real = tb_file_pread(file, aice->u.read.data, aice->u.read.size, aice->u.read.seek); - - // trace - tb_trace_d("read[%p]: %ld", file, real); - - // ok? - if (real > 0) - { - aice->u.read.real = real; - aice->state = TB_STATE_OK; - } - // closed? - else if (!real) aice->state = TB_STATE_CLOSED; - // failed? - else aice->state = TB_STATE_FAILED; - - // ok? - return 1; -} -static tb_long_t tb_aicp_file_spak_writ(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice && aice->code == TB_AICE_CODE_WRIT, -1); - tb_assert_and_check_return_val(aice->u.writ.data && aice->u.writ.size, -1); - - // the file - tb_file_ref_t file = tb_aico_file(aice->aico); - tb_assert_and_check_return_val(file, -1); - - // writ it from the given offset - tb_long_t real = tb_file_pwrit(file, aice->u.writ.data, aice->u.read.size, aice->u.writ.seek); - - // trace - tb_trace_d("writ[%p]: %ld", file, real); - - // ok? - if (real > 0) - { - aice->u.writ.real = real; - aice->state = TB_STATE_OK; - } - // closed? - else if (!real) aice->state = TB_STATE_CLOSED; - // failed? - else aice->state = TB_STATE_FAILED; - - // ok? - return 1; -} -static tb_long_t tb_aicp_file_spak_readv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice && aice->code == TB_AICE_CODE_READV, -1); - tb_assert_and_check_return_val(aice->u.readv.list && aice->u.readv.size, -1); - - // the file - tb_file_ref_t file = tb_aico_file(aice->aico); - tb_assert_and_check_return_val(file, -1); - - // read it from the given offset - tb_long_t real = tb_file_preadv(file, aice->u.readv.list, aice->u.readv.size, aice->u.readv.seek); - - // trace - tb_trace_d("readv[%p]: %ld", file, real); - - // ok? - if (real > 0) - { - aice->u.readv.real = real; - aice->state = TB_STATE_OK; - } - // closed? - else if (!real) aice->state = TB_STATE_CLOSED; - // failed? - else aice->state = TB_STATE_FAILED; - - // ok? - return 1; -} -static tb_long_t tb_aicp_file_spak_writv(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice && aice->code == TB_AICE_CODE_WRITV, -1); - tb_assert_and_check_return_val(aice->u.writv.list && aice->u.writv.size, -1); - - // the file - tb_file_ref_t file = tb_aico_file(aice->aico); - tb_assert_and_check_return_val(file, -1); - - // read it from the given offset - tb_long_t real = tb_file_pwritv(file, aice->u.writv.list, aice->u.writv.size, aice->u.writv.seek); - - // trace - tb_trace_d("writv[%p]: %ld", file, real); - - // ok? - if (real > 0) - { - aice->u.writv.real = real; - aice->state = TB_STATE_OK; - } - // closed? - else if (!real) aice->state = TB_STATE_CLOSED; - // failed? - else aice->state = TB_STATE_FAILED; - - // ok? - return 1; -} -static tb_long_t tb_aicp_file_spak_fsync(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(impl && aice && aice->code == TB_AICE_CODE_FSYNC, -1); - - // the file - tb_file_ref_t file = tb_aico_file(aice->aico); - tb_assert_and_check_return_val(file, -1); - - // done sync - tb_bool_t ok = tb_file_sync(file); - - // trace - tb_trace_d("fsync[%p]: %s", file, ok? "ok" : "no"); - - // ok? - aice->state = ok? TB_STATE_OK : TB_STATE_FAILED; - - // ok? - return 1; -} -static tb_void_t tb_aicp_file_kill(tb_aiop_ptor_impl_t* impl) -{ -} -static tb_void_t tb_aicp_file_poll(tb_aiop_ptor_impl_t* impl) -{ -} - diff --git a/core/src/tbox/src/tbox/asio/deprecated/impl/prefix.h b/core/src/tbox/src/tbox/asio/deprecated/impl/prefix.h deleted file mode 100644 index 35bc9ad22..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/impl/prefix.h +++ /dev/null @@ -1,323 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_ASIO_IMPL_PREFIX_H -#define TB_ASIO_IMPL_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../aicp.h" -#include "../aiop.h" -#include "../../../memory/memory.h" -#include "../../../platform/platform.h" -#include "../../../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the aioo impl type -typedef struct __tb_aioo_impl_t -{ - // the code - tb_size_t code; - - // the priv - tb_cpointer_t priv; - - // the socket - tb_socket_ref_t sock; - -}tb_aioo_impl_t; - -// the aico impl type -typedef struct __tb_aico_impl_t -{ - // the aicp - tb_aicp_ref_t aicp; - - // the type - tb_size_t type; - - // the handle - tb_handle_t handle; - - /*! the state - * - * <pre> - * TB_STATE_CLOSED - * TB_STATE_OPENED - * TB_STATE_KILLED - * TB_STATE_KILLING - * TB_STATE_PENDING - * </pre> - */ - tb_atomic_t state; - - // the timeout for aice - tb_atomic_t timeout[TB_AICO_TIMEOUT_MAXN]; - -#ifdef __tb_debug__ - // the func - tb_char_t const* func; - - // the file - tb_char_t const* file; - - // the line - tb_size_t line; -#endif - -}tb_aico_impl_t; - -// the aicp proactor impl type -struct __tb_aicp_impl_t; -typedef struct __tb_aicp_ptor_impl_t -{ - // aicp - struct __tb_aicp_impl_t* aicp; - - // the aico step - tb_size_t step; - - // kill - tb_void_t (*kill)(struct __tb_aicp_ptor_impl_t* ptor); - - // exit - tb_void_t (*exit)(struct __tb_aicp_ptor_impl_t* ptor); - - // addo - tb_bool_t (*addo)(struct __tb_aicp_ptor_impl_t* ptor, tb_aico_impl_t* aico); - - // kilo - tb_void_t (*kilo)(struct __tb_aicp_ptor_impl_t* ptor, tb_aico_impl_t* aico); - - // post - tb_bool_t (*post)(struct __tb_aicp_ptor_impl_t* ptor, tb_aice_ref_t aice); - - // loop: init - tb_handle_t (*loop_init)(struct __tb_aicp_ptor_impl_t* ptor); - - // loop: exit - tb_void_t (*loop_exit)(struct __tb_aicp_ptor_impl_t* ptor, tb_handle_t loop); - - // loop: spak - tb_long_t (*loop_spak)(struct __tb_aicp_ptor_impl_t* ptor, tb_handle_t loop, tb_aice_ref_t resp, tb_long_t timeout); - -}tb_aicp_ptor_impl_t; - -// the aiop reactor impl type -struct __tb_aiop_impl_t; -typedef struct __tb_aiop_rtor_impl_t -{ - // aiop - struct __tb_aiop_impl_t* aiop; - - // the supported aioe code - tb_size_t code; - - // exit - tb_void_t (*exit)(struct __tb_aiop_rtor_impl_t* rtor); - - // cler - tb_void_t (*cler)(struct __tb_aiop_rtor_impl_t* rtor); - - // addo - tb_bool_t (*addo)(struct __tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo); - - // delo - tb_bool_t (*delo)(struct __tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo); - - // post - tb_bool_t (*post)(struct __tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t aioe); - - // wait - tb_long_t (*wait)(struct __tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout); - -}tb_aiop_rtor_impl_t; - -// the aicp impl type -typedef struct __tb_aicp_impl_t -{ - // the object maxn - tb_size_t maxn; - - // the ptor - tb_aicp_ptor_impl_t* ptor; - - // the worker size - tb_atomic_t work; - - // the pool - tb_fixed_pool_ref_t pool; - - // the pool lock - tb_spinlock_t lock; - - // kill it? - tb_atomic_t kill; - - // killall it? - tb_atomic_t kill_all; - -}tb_aicp_impl_t; - -// the aiop impl type -typedef struct __tb_aiop_impl_t -{ - // the aioo maxn - tb_size_t maxn; - - // the aioo pool - tb_fixed_pool_ref_t pool; - - // the pool lock - tb_spinlock_t lock; - - // the reactor - tb_aiop_rtor_impl_t* rtor; - - // the spak - tb_socket_ref_t spak[2]; - -}tb_aiop_impl_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* init aicp proactor - * - * @param aicp the aicp impl - * - * @return the aicp proactor impl - */ -tb_aicp_ptor_impl_t* tb_aicp_ptor_impl_init(tb_aicp_impl_t* aicp); - -/* init aiop reactor - * - * @param aiop the aiop impl - * - * @return the aiop reactor impl - */ -tb_aiop_rtor_impl_t* tb_aiop_rtor_impl_init(tb_aiop_impl_t* aiop); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * inlines - */ -static __tb_inline__ tb_bool_t tb_aico_impl_is_killed(tb_aico_impl_t* aico) -{ - // check - tb_assert_and_check_return_val(aico, tb_false); - - // the state - tb_size_t state = tb_atomic_get(&aico->state); - - // killing or exiting or killed? - return (state == TB_STATE_KILLING) || (state == TB_STATE_KILLED); -} -static __tb_inline__ tb_size_t tb_aice_impl_priority(tb_aice_ref_t aice) -{ - // the priorities - static tb_size_t s_priorities[] = - { - 1 - - , 1 - , 0 // acpt - , 0 // conn - , 1 - , 1 - , 1 - , 1 - , 1 - , 1 - , 1 - , 1 - , 1 - - , 1 - , 1 - , 1 - , 1 - , 1 - - , 0 // task - , 0 // clos - }; - tb_assert_and_check_return_val(aice->code && aice->code < tb_arrayn(s_priorities), 1); - - // the priority - return s_priorities[aice->code]; -} -static __tb_inline__ tb_long_t tb_aico_impl_timeout_from_code(tb_aico_impl_t* aico, tb_size_t code) -{ - // init the timeout type - static tb_size_t type[] = - { - -1 - - , -1 - , TB_AICO_TIMEOUT_CONN - , TB_AICO_TIMEOUT_RECV - , TB_AICO_TIMEOUT_SEND - , TB_AICO_TIMEOUT_RECV - , TB_AICO_TIMEOUT_SEND - , TB_AICO_TIMEOUT_RECV - , TB_AICO_TIMEOUT_SEND - , TB_AICO_TIMEOUT_RECV - , TB_AICO_TIMEOUT_SEND - , TB_AICO_TIMEOUT_SEND - - , -1 - , -1 - , -1 - , -1 - , -1 - - , -1 - }; - tb_assert_and_check_return_val(code < tb_arrayn(type), -1); - - // no timeout? - tb_check_return_val(type[code] != -1, -1); - - // timeout - return tb_aico_timeout((tb_aico_ref_t)aico, type[code]); -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/prefix.h b/core/src/tbox/src/tbox/asio/deprecated/prefix.h deleted file mode 100644 index 7250b5905..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/prefix.h +++ /dev/null @@ -1,139 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_ASIO_DEPRECATED_PREFIX_H -#define TB_ASIO_DEPRECATED_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../../platform/prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the aioo ref type -typedef __tb_typeref__(aioo); - -/// the aico ref type -typedef __tb_typeref__(aico); - -/*! the aico pool ref type - * - * <pre> - * |------------------------------------------------| - * | astream | - * |------------------------------------------------| - * | addr | http | file | sock | .. | - * '------------------------------------------------' - * | - * init: [aicp] - * | - * |------------------------------------------------| - * addo: | aico0 aico1 aico2 aico3 ... | <= sock, file, and task aico - * '------------------------------------------------' - * | - * [aicp] - * | - * post: |------------------------------------------------| <= only post one aice for the same aico util the aice is finished - * aice: | aice0 aice1 aice2 aice3 ... | <--------------------------------------------------------------------------------- - * '------------------------------------------------' | - * | | - * [aicp] | - * | <= input aices | - * | | - * '-------------------------------------------------------------- | - * | | | - * |--------------------------------------------------------------------------------------------------| | - * | unix proactor | | windows proactor | | - * |-----------------------------------------------------------------------|--------------------------| | - * | | | | | | - * | continue to spak aice | | |----- | | - * | -------------------------------> | | | | | | - * | | \/ [lock] | \/ | | | - * aiop: |------|-------|-------|-------|---- ... --|-----| |-----| | done post | | - * aico: | aico0 aico1 aico2 aico3 ... | | | | | | | | | - * wait: |------|-------|-------|-------|---- ... --|-----| |aice4| | |----------------| | | - * | | | | | | | | | | | | - * | aice0 aice2 | |aice5| | | | | | - * | | | | | | | | | | | | - * | aice1 ... | |aice6| | | iocp | | | - * | | | | | | | | | | | - * | aice3 | |aice7| | | | | | - * | | | | | | | | | | | - * | ... | | ... | | | | | | - * | | | | | | | | wait0 wait1 .. | | | - * | | | | | ---------------- | | - * | wait poll | |queue| | | | | | - * '------------------------------------------------' '-----'-----------'--------------------------' | - * /\ | [lock] | | | - * | | | | | - * | no data? wait aice --------------------------->----------------- | - * |<-----------------------------| worker0 | worker1 | ... | <= done loop for workers | - * -------------------<------------------------- | - * | | | | - * |---------------------------------------------| | - * | aice0 | aice2 | ... | | - * | aice1 | aice3 | ... | <= output aices | - * | ... | aice4 | ... | | - * | ... | ... | ... | | - * '---------------------------------------------' | - * | | | | - * |---------------------------------------------| | - * | caller0 | caller2 | ... | | - * | caller1 | ... | ... | <= done callers | - * | ... | caller3 | ... | | - * | ... | ... | ... | | - * '---------------------------------------------' | - * | | | - * ... ... | - * post aice end ---- | - * | | | - * '---------------------|------------------------------------------------>' - * | - * kill: ... | - * | | - * exit: ... <---------' - * - * </pre> - * - */ -typedef __tb_typeref__(aicp); - -/*! the asio poll pool type - * - * @note only for sock and using level triggered mode - * - * <pre> - * objs: |-----|------|------|--- ... ...---|-------| - * wait: | | - * evet: read writ ... - * </pre> - * - */ -typedef __tb_typeref__(aiop); - -#endif diff --git a/core/src/tbox/src/tbox/asio/deprecated/ssl.c b/core/src/tbox/src/tbox/asio/deprecated/ssl.c deleted file mode 100644 index 3de448105..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/ssl.c +++ /dev/null @@ -1,1366 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file ssl.c - * @ingroup asio - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "aicp_ssl" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "ssl.h" -#include "aico.h" -#include "aicp.h" -#include "../../network/network.h" -#include "../../platform/platform.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the aicp impl open type -typedef struct __tb_aicp_ssl_open_t -{ - // the func - tb_aicp_ssl_open_func_t func; - - // the priv - tb_cpointer_t priv; - -}tb_aicp_ssl_open_t; - -// the aicp impl clos type -typedef struct __tb_aicp_ssl_clos_t -{ - // the func - tb_aicp_ssl_clos_func_t func; - - // the priv - tb_cpointer_t priv; - -}tb_aicp_ssl_clos_t; - -// the aicp impl read type -typedef struct __tb_aicp_ssl_read_t -{ - // the func - tb_aicp_ssl_read_func_t func; - - // the data - tb_byte_t* data; - - // the size - tb_size_t size; - - // the priv - tb_cpointer_t priv; - - // the delay - tb_size_t delay; - -}tb_aicp_ssl_read_t; - -// the aicp impl writ type -typedef struct __tb_aicp_ssl_writ_t -{ - // the func - tb_aicp_ssl_writ_func_t func; - - // the data - tb_byte_t const* data; - - // the size - tb_size_t size; - - // the priv - tb_cpointer_t priv; - -}tb_aicp_ssl_writ_t; - -// the aicp impl task type -typedef struct __tb_aicp_ssl_task_t -{ - // the func - tb_aicp_ssl_task_func_t func; - - // the priv - tb_cpointer_t priv; - -}tb_aicp_ssl_task_t; - -/// the aicp impl close opening type -typedef struct __tb_aicp_ssl_clos_opening_t -{ - /// the func - tb_aicp_ssl_open_func_t func; - - /// the priv - tb_cpointer_t priv; - - /// the open state - tb_size_t state; - -}tb_aicp_ssl_clos_opening_t; - -// the aicp impl type -typedef struct __tb_aicp_ssl_impl_t -{ - // the ssl - tb_ssl_ref_t ssl; - - // the aicp - tb_aicp_ref_t aicp; - - // the aico - tb_aico_ref_t aico; - - // the func - union - { - tb_aicp_ssl_open_t open; - tb_aicp_ssl_read_t read; - tb_aicp_ssl_writ_t writ; - tb_aicp_ssl_task_t task; - tb_aicp_ssl_clos_t clos; - - } func; - - // the open and func - union - { - tb_aicp_ssl_read_t read; - tb_aicp_ssl_writ_t writ; - - } open_and; - - // the clos opening - tb_aicp_ssl_clos_opening_t clos_opening; - - // the post - struct - { - // the post func - tb_bool_t (*func)(tb_aice_ref_t aice); - - // the post delay - tb_size_t delay; - - // the real size - tb_long_t real; - - // the read or writ data - tb_byte_t* data; - - // the read or writ size - tb_size_t size; - - // post read? - tb_bool_t read; - - // have post? - tb_bool_t post; - - } post; - - // the timeout - tb_long_t timeout; - - /* the state - * - * TB_STATE_CLOSED - * TB_STATE_OPENED - * TB_STATE_OPENING - * TB_STATE_KILLING - */ - tb_atomic_t state; - - // the read data - tb_buffer_t read_data; - - // the writ data - tb_buffer_t writ_data; - -}tb_aicp_ssl_impl_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_long_t tb_aicp_ssl_fill_read(tb_aicp_ssl_impl_t* impl, tb_byte_t* data, tb_size_t size) -{ - // check - tb_assert_and_check_return_val(impl, -1); - - // done - tb_long_t real = -1; - do - { - // check - tb_assert_and_check_break(impl->aico); - tb_assert_and_check_break(data && size && impl->post.real >= 0); - - // save real - tb_size_t read_real = impl->post.real; - - // clear real - impl->post.real = -1; - - // check - tb_assert_and_check_break(read_real <= size); - - // the data and size - tb_byte_t* read_data = tb_buffer_data(&impl->read_data); - tb_size_t read_size = tb_buffer_size(&impl->read_data); - tb_assert_and_check_break(read_data && read_size && size <= read_size); - - // copy data - tb_memcpy(data, read_data, read_real); - - // trace - tb_trace_d("[aico:%p]: read: fill: %lu: ok", impl->aico, read_real); - - // read ok - real = read_real; - - } while (0); - - // ok? - return real; -} -static tb_long_t tb_aicp_ssl_fill_writ(tb_aicp_ssl_impl_t* impl, tb_byte_t const* data, tb_size_t size) -{ - // check - tb_assert_and_check_return_val(impl, -1); - - // done - tb_long_t real = -1; - do - { - // check - tb_assert_and_check_break(impl->aico); - tb_assert_and_check_break(size && impl->post.real >= 0); - - // save real - tb_size_t writ_real = impl->post.real; - - // clear real - impl->post.real = -1; - - // check - tb_assert_and_check_break(writ_real <= size); - - // trace - tb_trace_d("[aico:%p]: writ: try: %lu: ok", impl->aico, writ_real); - - // writ ok - real = writ_real; - - } while (0); - - // ok? - return real; -} -static tb_bool_t tb_aicp_ssl_done_post(tb_aicp_ssl_impl_t* impl) -{ - // check - tb_assert_and_check_return_val(impl, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // check - tb_assert_and_check_break(impl->post.post && impl->post.data && impl->post.size && impl->post.func); - - // check - tb_assert_and_check_break(impl->aico); - - // post read? - if (impl->post.read) - { - // trace - tb_trace_d("[aico:%p]: post: read: %lu: ..", impl->aico, impl->post.size); - - // post read - if (!tb_aico_recv_after(impl->aico, impl->post.delay, impl->post.data, impl->post.size, impl->post.func, impl)) break; - } - // post writ? - else - { - // trace - tb_trace_d("[aico:%p]: post: writ: %lu: ..", impl->aico, impl->post.size); - - // post writ - if (!tb_aico_send_after(impl->aico, impl->post.delay, impl->post.data, impl->post.size, impl->post.func, impl)) break; - } - - // delay only for first - impl->post.delay = 0; - - // ok - ok = tb_true; - - } while (0); - - // ok? - return ok; -} -static tb_void_t tb_aicp_ssl_clos_clear(tb_aicp_ssl_impl_t* impl) -{ - // check - tb_assert_and_check_return(impl); - - // close impl - if (impl->ssl && impl->aico) - { - // init bio sock, need some blocking time for closing - tb_ssl_set_bio_sock(impl->ssl, tb_aico_sock(impl->aico)); - - // close it - tb_ssl_clos(impl->ssl); - } - - // clear data - tb_buffer_clear(&impl->read_data); - tb_buffer_clear(&impl->writ_data); - - // clear real - impl->post.real = 0; - impl->post.real = 0; - - // closed - tb_atomic_set(&impl->state, TB_STATE_CLOSED); -} -static tb_void_t tb_aicp_ssl_clos_opening(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return(impl); - - // trace - tb_trace_d("[aico:%p]: clos: opening: state: %s", impl->aico, tb_state_cstr(impl->clos_opening.state)); - - // done func - if (impl->clos_opening.func) impl->clos_opening.func(ssl, impl->clos_opening.state, impl->clos_opening.priv); -} -static tb_bool_t tb_aicp_ssl_open_func(tb_aicp_ssl_impl_t* impl, tb_size_t state, tb_aicp_ssl_open_func_t func, tb_cpointer_t priv) -{ - // check - tb_assert_and_check_return_val(impl, tb_false); - - // ok? - tb_bool_t ok = tb_true; - if (state == TB_STATE_OK || !impl->aico) - { - // opened - tb_atomic_set(&impl->state, TB_STATE_OPENED); - - // done func - if (func) ok = func((tb_aicp_ssl_ref_t)impl, state, priv); - } - // failed? - else - { - // init func and state - impl->clos_opening.func = func; - impl->clos_opening.priv = priv; - impl->clos_opening.state = state; - - // close it - tb_aicp_ssl_clos((tb_aicp_ssl_ref_t)impl, tb_aicp_ssl_clos_opening, tb_null); - } - - // ok? - return ok; -} -static tb_bool_t tb_aicp_ssl_open_done(tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(aice && (aice->code == TB_AICE_CODE_RECV || aice->code == TB_AICE_CODE_SEND), tb_false); - - // the impl - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)aice->priv; - tb_assert_and_check_return_val(impl && impl->func.open.func, tb_false); - - // the real - tb_size_t real = aice->code == TB_AICE_CODE_RECV? aice->u.recv.real : aice->u.send.real; - - // trace - tb_trace_d("[aico:%p]: open: done: real: %lu, state: %s", impl->aico, real, tb_state_cstr(aice->state)); - - // done - tb_size_t state = TB_STATE_SOCK_SSL_UNKNOWN_ERROR; - do - { - // clear post - impl->post.post = tb_false; - impl->post.data = tb_null; - impl->post.size = 0; - - // failed or closed? - if (aice->state != TB_STATE_OK) - { - state = aice->state; - break; - } - - // save the real size - impl->post.real = real; - - // trace - tb_trace_d("[aico:%p]: open: done: try: ..", impl->aico); - - // try opening it - tb_long_t ok = tb_ssl_open_try(impl->ssl); - - // trace - tb_trace_d("[aico:%p]: open: done: try: %ld", impl->aico, ok); - - // ok? - if (ok > 0) - { - // done func - tb_aicp_ssl_open_func(impl, TB_STATE_OK, impl->func.open.func, impl->func.open.priv); - } - // failed? - else if (ok < 0) - { - // save state - state = tb_ssl_state(impl->ssl); - break; - } - // have post? continue it - else if (impl->post.post) - { - // post it - if (!tb_aicp_ssl_done_post(impl)) - { - // trace - tb_trace_e("[aico:%p]: open: done: post failed!", impl->aico); - break; - } - } - else - { - // trace - tb_trace_d("[aico:%p]: open: done: no post!", impl->aico); - } - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - tb_aicp_ssl_open_func(impl, state, impl->func.open.func, impl->func.open.priv); - } - - // ok - return tb_true; -} -static tb_bool_t tb_aicp_ssl_read_done(tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(aice && (aice->code == TB_AICE_CODE_RECV || aice->code == TB_AICE_CODE_SEND), tb_false); - - // the impl - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)aice->priv; - tb_assert_and_check_return_val(impl && impl->func.read.func, tb_false); - - // the real - tb_size_t real = aice->code == TB_AICE_CODE_RECV? aice->u.recv.real : aice->u.send.real; - - // trace - tb_trace_d("[aico:%p]: read: done: real: %lu, state: %s", impl->aico, real, tb_state_cstr(aice->state)); - - // done - tb_size_t state = TB_STATE_SOCK_SSL_UNKNOWN_ERROR; - do - { - // clear post - impl->post.post = tb_false; - impl->post.data = tb_null; - impl->post.size = 0; - - // failed or closed? - if (aice->state != TB_STATE_OK) - { - state = aice->state; - break; - } - - // save the real size - impl->post.real = real; - - // trace - tb_trace_d("[aico:%p]: read: done: try: %lu: ..", impl->aico, impl->func.read.size); - - // try reading it - tb_long_t real = tb_ssl_read(impl->ssl, impl->func.read.data, impl->func.read.size); - - // trace - tb_trace_d("[aico:%p]: read: done: try: %lu: %ld", impl->aico, impl->func.read.size, real); - - // ok? - if (real > 0) - { - // done func - impl->func.read.func((tb_aicp_ssl_ref_t)impl, TB_STATE_OK, impl->func.read.data, real, impl->func.read.size, impl->func.read.priv); - } - // failed? - else if (real < 0) - { - // save state - state = tb_ssl_state(impl->ssl); - break; - } - // have post? continue it - else if (impl->post.post) - { - // post it - if (!tb_aicp_ssl_done_post(impl)) - { - // trace - tb_trace_e("[aico:%p]: read: done: post failed!", impl->aico); - break; - } - } - else - { - // trace - tb_trace_d("[aico:%p]: read: done: no post!", impl->aico); - - // done func - impl->func.read.func((tb_aicp_ssl_ref_t)impl, TB_STATE_OK, impl->func.read.data, 0, impl->func.read.size, impl->func.read.priv); - } - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - impl->func.read.func((tb_aicp_ssl_ref_t)impl, state, impl->func.read.data, 0, impl->func.read.size, impl->func.read.priv); - } - - // ok - return tb_true; -} -static tb_bool_t tb_aicp_ssl_writ_done(tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(aice && (aice->code == TB_AICE_CODE_RECV || aice->code == TB_AICE_CODE_SEND), tb_false); - - // the impl - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)aice->priv; - tb_assert_and_check_return_val(impl && impl->func.writ.func, tb_false); - - // the real - tb_size_t real = aice->code == TB_AICE_CODE_RECV? aice->u.recv.real : aice->u.send.real; - - // trace - tb_trace_d("[aico:%p]: writ: done: real: %lu, state: %s", impl->aico, real, tb_state_cstr(aice->state)); - - // done - tb_size_t state = TB_STATE_SOCK_SSL_UNKNOWN_ERROR; - do - { - // clear post - impl->post.post = tb_false; - impl->post.data = tb_null; - impl->post.size = 0; - - // failed or closed? - if (aice->state != TB_STATE_OK) - { - state = aice->state; - break; - } - - // save the real size - impl->post.real = real; - - // trace - tb_trace_d("[aico:%p]: writ: done: try: %lu: ..", impl->aico, impl->func.writ.size); - - // try writing it - tb_long_t real = tb_ssl_writ(impl->ssl, impl->func.writ.data, impl->func.writ.size); - - // trace - tb_trace_d("[aico:%p]: writ: done: try: %lu: %ld", impl->aico, impl->func.writ.size, real); - - // ok? - if (real > 0) - { - // done func - impl->func.writ.func((tb_aicp_ssl_ref_t)impl, TB_STATE_OK, impl->func.writ.data, real, impl->func.writ.size, impl->func.writ.priv); - } - // failed? - else if (real < 0) - { - // save state - state = tb_ssl_state(impl->ssl); - break; - } - // have post? continue it - else if (impl->post.post) - { - // post it - if (!tb_aicp_ssl_done_post(impl)) - { - // trace - tb_trace_e("[aico:%p]: writ: done: post failed!", impl->aico); - break; - } - } - else - { - // trace - tb_trace_d("[aico:%p]: writ: done: no post!", impl->aico); - - // done func - impl->func.writ.func((tb_aicp_ssl_ref_t)impl, TB_STATE_OK, impl->func.writ.data, 0, impl->func.writ.size, impl->func.writ.priv); - } - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - impl->func.writ.func((tb_aicp_ssl_ref_t)impl, state, impl->func.writ.data, 0, impl->func.writ.size, impl->func.writ.priv); - } - - // ok - return tb_true; -} -static tb_long_t tb_aicp_ssl_read_func(tb_cpointer_t priv, tb_byte_t* data, tb_size_t size) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->post.func && !impl->post.post, -1); - - // done - tb_size_t state = TB_STATE_SOCK_SSL_UNKNOWN_ERROR; - do - { - // fill to read it? - if (impl->post.real >= 0) return tb_aicp_ssl_fill_read(impl, data, size); - - // resize data - if (tb_buffer_size(&impl->read_data) < size) - tb_buffer_resize(&impl->read_data, size); - - // the data and size - tb_byte_t* read_data = tb_buffer_data(&impl->read_data); - tb_size_t read_size = tb_buffer_size(&impl->read_data); - tb_assert_and_check_break(read_data && read_size && size <= read_size); - - // post read - impl->post.post = tb_true; - impl->post.read = tb_true; - impl->post.data = read_data; - impl->post.size = size; - - // ok - state = TB_STATE_OK; - - } while (0); - - // read failed or continue? - return state != TB_STATE_OK? -1 : 0; -} -static tb_long_t tb_aicp_ssl_writ_func(tb_cpointer_t priv, tb_byte_t const* data, tb_size_t size) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)priv; - tb_assert_and_check_return_val(impl && impl->post.func && !impl->post.post, -1); - - // done - tb_size_t state = TB_STATE_SOCK_SSL_UNKNOWN_ERROR; - do - { - // fill to writ it? - if (impl->post.real >= 0) return tb_aicp_ssl_fill_writ(impl, data, size); - - // save data - tb_buffer_memncpy(&impl->writ_data, data, size); - - // the data and size - tb_byte_t* writ_data = tb_buffer_data(&impl->writ_data); - tb_size_t writ_size = tb_buffer_size(&impl->writ_data); - tb_assert_and_check_break(writ_data && writ_size && size == writ_size); - - // post writ - impl->post.post = tb_true; - impl->post.read = tb_false; - impl->post.data = writ_data; - impl->post.size = writ_size; - - // ok - state = TB_STATE_OK; - - } while (0); - - // ok? - return state != TB_STATE_OK? -1 : 0; -} -static tb_bool_t tb_aicp_ssl_open_and_read(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_read_t* read = (tb_aicp_ssl_read_t*)priv; - tb_assert_and_check_return_val(ssl && read && read->func, tb_false); - - // done - tb_bool_t ok = tb_true; - do - { - // check - tb_check_break(state == TB_STATE_OK); - - // clear state - state = TB_STATE_SOCK_SSL_UNKNOWN_ERROR; - - // post read - if (!tb_aicp_ssl_read(ssl, read->data, read->size, read->func, read->priv)) break; - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - ok = read->func(ssl, state, read->data, 0, read->size, read->priv); - } - - // ok? - return ok; -} -static tb_bool_t tb_aicp_ssl_open_and_writ(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_writ_t* writ = (tb_aicp_ssl_writ_t*)priv; - tb_assert_and_check_return_val(ssl && writ && writ->func, tb_false); - - // done - tb_bool_t ok = tb_true; - do - { - // check - tb_check_break(state == TB_STATE_OK); - - // clear state - state = TB_STATE_SOCK_SSL_UNKNOWN_ERROR; - - // post writ - if (!tb_aicp_ssl_writ(ssl, writ->data, writ->size, writ->func, writ->priv)) break; - - // ok - state = TB_STATE_OK; - - } while (0); - - // failed? - if (state != TB_STATE_OK) - { - // done func - ok = writ->func(ssl, state, writ->data, 0, writ->size, writ->priv); - } - - // ok? - return ok; -} -static tb_bool_t tb_aicp_ssl_done_task(tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(aice && aice->code == TB_AICE_CODE_RUNTASK, tb_false); - - // the impl - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)aice->priv; - tb_assert_and_check_return_val(impl && impl->func.task.func, tb_false); - - // trace - tb_trace_d("[aico:%p]: task: done: state: %s", impl->aico, tb_state_cstr(aice->state)); - - // done func - impl->func.task.func((tb_aicp_ssl_ref_t)impl, aice->state, impl->post.delay, impl->func.task.priv); - - // ok - return tb_true; -} -static tb_bool_t tb_aicp_ssl_done_clos(tb_aice_ref_t aice) -{ - // check - tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_RUNTASK, tb_false); - - // the impl - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)aice->priv; - tb_assert_and_check_return_val(impl && impl->func.clos.func, tb_false); - - // trace - tb_trace_d("[aico:%p]: clos: notify: ..", impl->aico); - - // clear impl - tb_aicp_ssl_clos_clear(impl); - - // done func - impl->func.clos.func((tb_aicp_ssl_ref_t)impl, TB_STATE_OK, impl->func.clos.priv); - - // trace - tb_trace_d("[aico:%p]: clos: notify: ok", impl->aico); - - // ok - return tb_true; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_aicp_ssl_ref_t tb_aicp_ssl_init(tb_aicp_ref_t aicp, tb_bool_t bserver) -{ - // check - tb_assert_and_check_return_val(aicp, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_aicp_ssl_impl_t* impl = tb_null; - do - { - // make impl - impl = tb_malloc0_type(tb_aicp_ssl_impl_t); - tb_assert_and_check_break(impl); - - // init state - impl->state = TB_STATE_CLOSED; - - // init aicp - impl->aicp = aicp; - - // init impl - impl->ssl = tb_ssl_init(bserver); - tb_assert_and_check_break(impl->ssl); - - // init read data - if (!tb_buffer_init(&impl->read_data)) break; - - // init writ data - if (!tb_buffer_init(&impl->writ_data)) break; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (impl) tb_aicp_ssl_exit((tb_aicp_ssl_ref_t)impl); - impl = tb_null; - } - - // ok? - return (tb_aicp_ssl_ref_t)impl; -} -tb_void_t tb_aicp_ssl_kill(tb_aicp_ssl_ref_t ssl) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return(impl); - - // kill it - tb_size_t state = tb_atomic_fetch_and_set(&impl->state, TB_STATE_KILLING); - tb_check_return(state != TB_STATE_KILLING); - - // trace - tb_trace_d("[aico:%p]: kill: ..", impl->aico); - - // kill aico - if (impl->aico) tb_aico_kill(impl->aico); -} -tb_bool_t tb_aicp_ssl_exit(tb_aicp_ssl_ref_t ssl) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl, tb_false); - - // trace - tb_trace_d("[aico:%p]: exit: ..", impl->aico); - - // try closing it - tb_size_t tryn = 30; - tb_bool_t ok = tb_false; - while (!(ok = tb_aicp_ssl_clos_try(ssl)) && tryn--) - { - // wait some time - tb_msleep(200); - } - - // close failed? - if (!ok) - { - // trace - tb_trace_e("[aico:%p]: exit: failed!", impl->aico); - return tb_false; - } - - // exit impl - if (impl->ssl) tb_ssl_exit(impl->ssl); - impl->ssl = tb_null; - - // exit data - tb_buffer_exit(&impl->read_data); - tb_buffer_exit(&impl->writ_data); - - // trace - tb_trace_d("[aico:%p]: exit: ok", impl->aico); - - // exit it - tb_free(impl); - - // ok - return tb_true; -} -tb_void_t tb_aicp_ssl_set_aico(tb_aicp_ssl_ref_t ssl, tb_aico_ref_t aico) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return(impl); - - // save aico - impl->aico = aico; -} -tb_void_t tb_aicp_ssl_set_timeout(tb_aicp_ssl_ref_t ssl, tb_long_t timeout) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return(impl); - - // save timeout - impl->timeout = timeout; -} -tb_bool_t tb_aicp_ssl_open(tb_aicp_ssl_ref_t ssl, tb_aicp_ssl_open_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl && func, tb_false); - - // done - do - { - // set opening - tb_size_t state = tb_atomic_fetch_and_pset(&impl->state, TB_STATE_CLOSED, TB_STATE_OPENING); - - // opened? done func directly - if (state == TB_STATE_OPENED) - { - func(ssl, TB_STATE_OK, priv); - break; - } - - // must be closed - tb_assert_and_check_return_val(state == TB_STATE_CLOSED, tb_false); - - // check - tb_assert_and_check_return_val(impl->aicp && impl->ssl && impl->aico, tb_false); - - // killed? - if (TB_STATE_KILLING == tb_atomic_get(&impl->state)) - { - // done func - tb_aicp_ssl_open_func(impl, TB_STATE_KILLED, func, priv); - break; - } - - // init timeout - if (impl->timeout) - { - tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_RECV, impl->timeout); - tb_aico_timeout_set(impl->aico, TB_AICO_TIMEOUT_SEND, impl->timeout); - } - - // save func - impl->func.open.func = func; - impl->func.open.priv = priv; - - // init post - impl->post.func = tb_aicp_ssl_open_done; - impl->post.delay = 0; - impl->post.post = tb_false; - impl->post.data = tb_null; - impl->post.size = 0; - impl->post.real = -1; - - // init post func - tb_ssl_set_bio_func(impl->ssl, tb_aicp_ssl_read_func, tb_aicp_ssl_writ_func, tb_null, impl); - - // try opening it - tb_long_t r = tb_ssl_open_try(impl->ssl); - - // ok - if (r > 0) - { - // done func - tb_aicp_ssl_open_func(impl, TB_STATE_OK, func, priv); - } - // failed? - else if (r < 0) - { - // done func - tb_aicp_ssl_open_func(impl, tb_ssl_state(impl->ssl), func, priv); - } - // have post? continue it - else if (impl->post.post) - { - // post it - if (!tb_aicp_ssl_done_post(impl)) - { - // trace - tb_trace_e("[aico:%p]: open: post failed!", impl->aico); - - // done func - tb_aicp_ssl_open_func(impl, TB_STATE_SOCK_SSL_UNKNOWN_ERROR, func, priv); - } - } - else - { - // trace - tb_trace_e("[aico:%p]: open: no post!", impl->aico); - - // done func - tb_aicp_ssl_open_func(impl, TB_STATE_SOCK_SSL_UNKNOWN_ERROR, func, priv); - } - - } while (0); - - // post or done func ok - return tb_true; -} -tb_bool_t tb_aicp_ssl_clos(tb_aicp_ssl_ref_t ssl, tb_aicp_ssl_clos_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl && func, tb_false); - - // trace - tb_trace_d("[aico:%p]: clos: ..", impl->aico); - - // try closing ok? - if (tb_aicp_ssl_clos_try(ssl)) - { - // done func - func(ssl, TB_STATE_OK, priv); - return tb_true; - } - - // init func - impl->func.clos.func = func; - impl->func.clos.priv = priv; - - // clos aico - if (impl->aico && tb_aico_task_run(impl->aico, 0, tb_aicp_ssl_done_clos, impl)); - else - { - // clear impl - tb_aicp_ssl_clos_clear(impl); - - // done func - impl->func.clos.func(ssl, TB_STATE_OK, impl->func.clos.priv); - } - - // ok - return tb_true; -} -tb_bool_t tb_aicp_ssl_clos_try(tb_aicp_ssl_ref_t ssl) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl, tb_false); - - // trace - tb_trace_d("[aico:%p]: clos: try: ..", impl->aico); - - // done - tb_bool_t ok = tb_true; - do - { - // closed? ok - if (TB_STATE_CLOSED == tb_atomic_get(&impl->state)) break; - - // no aico? ok - if (!impl->aico) break; - - // failed - ok = tb_false; - - } while (0); - - // ok? closed - if (ok) tb_atomic_set(&impl->state, TB_STATE_CLOSED); - - // trace - tb_trace_d("[aico:%p]: clos: try: %s", impl->aico, ok? "ok" : "no"); - - // ok? - return ok; -} -tb_bool_t tb_aicp_ssl_read(tb_aicp_ssl_ref_t ssl, tb_byte_t* data, tb_size_t size, tb_aicp_ssl_read_func_t func, tb_cpointer_t priv) -{ - return tb_aicp_ssl_read_after(ssl, 0, data, size, func, priv); -} -tb_bool_t tb_aicp_ssl_writ(tb_aicp_ssl_ref_t ssl, tb_byte_t const* data, tb_size_t size, tb_aicp_ssl_writ_func_t func, tb_cpointer_t priv) -{ - return tb_aicp_ssl_writ_after(ssl, 0, data, size, func, priv); -} -tb_bool_t tb_aicp_ssl_read_after(tb_aicp_ssl_ref_t ssl, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_aicp_ssl_read_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl && data && size && func, tb_false); - - // trace - tb_trace_d("[aico:%p]: read: %lu, after: %lu", impl->aico, size, delay); - - // opened? - tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->state), tb_false); - - // check - tb_assert_and_check_return_val(impl->aicp && impl->ssl && impl->aico, tb_false); - - // done - do - { - // save func - impl->func.read.func = func; - impl->func.read.priv = priv; - impl->func.read.data = data; - impl->func.read.size = size; - - // init post - impl->post.func = tb_aicp_ssl_read_done; - impl->post.delay = delay; - impl->post.post = tb_false; - impl->post.data = tb_null; - impl->post.size = 0; - impl->post.real = -1; - - // init post func - tb_ssl_set_bio_func(impl->ssl, tb_aicp_ssl_read_func, tb_aicp_ssl_writ_func, tb_null, impl); - - // try reading it - tb_long_t real = tb_ssl_read(impl->ssl, data, size); - - // ok - if (real > 0) - { - // done func - func(ssl, TB_STATE_OK, data, real, size, priv); - } - // failed? - else if (real < 0) - { - // done func - func(ssl, tb_ssl_state(impl->ssl), data, 0, size, priv); - } - // have post? continue it - else if (impl->post.post) - { - // post it - if (!tb_aicp_ssl_done_post(impl)) - { - // trace - tb_trace_e("[aico:%p]: read: post failed!", impl->aico); - - // done func - func(ssl, TB_STATE_SOCK_SSL_UNKNOWN_ERROR, data, 0, size, priv); - } - } - else - { - // trace - tb_trace_e("[aico:%p]: read: no post!", impl->aico); - - // done func - func(ssl, TB_STATE_SOCK_SSL_UNKNOWN_ERROR, data, 0, size, priv); - } - - } while (0); - - // post or done func ok - return tb_true; -} -tb_bool_t tb_aicp_ssl_writ_after(tb_aicp_ssl_ref_t ssl, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_aicp_ssl_writ_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl && data && size && func, tb_false); - - // trace - tb_trace_d("[aico:%p]: writ: %lu, after: %lu", impl->aico, size, delay); - - // opened? - tb_assert_and_check_return_val(TB_STATE_OPENED == tb_atomic_get(&impl->state), tb_false); - - // check - tb_assert_and_check_return_val(impl->aicp && impl->ssl && impl->aico, tb_false); - - // done - do - { - // save func - impl->func.writ.func = func; - impl->func.writ.priv = priv; - impl->func.writ.data = data; - impl->func.writ.size = size; - - // init post - impl->post.func = tb_aicp_ssl_writ_done; - impl->post.delay = delay; - impl->post.post = tb_false; - impl->post.data = tb_null; - impl->post.size = 0; - impl->post.real = -1; - - // init post func - tb_ssl_set_bio_func(impl->ssl, tb_aicp_ssl_read_func, tb_aicp_ssl_writ_func, tb_null, impl); - - // try writing it - tb_long_t real = tb_ssl_writ(impl->ssl, data, size); - - // ok - if (real > 0) - { - // done func - func(ssl, TB_STATE_OK, data, real, size, priv); - } - // failed? - else if (real < 0) - { - // done func - func(ssl, tb_ssl_state(impl->ssl), data, 0, size, priv); - } - // have post? continue it - else if (impl->post.post) - { - // post it - if (!tb_aicp_ssl_done_post(impl)) - { - // trace - tb_trace_e("[aico:%p]: writ: post failed!", impl->aico); - - // done func - func(ssl, TB_STATE_SOCK_SSL_UNKNOWN_ERROR, data, 0, size, priv); - } - } - else - { - // trace - tb_trace_e("[aico:%p]: writ: no post!", impl->aico); - - // done func - func(ssl, TB_STATE_SOCK_SSL_UNKNOWN_ERROR, data, 0, size, priv); - } - - } while (0); - - // post or done func ok - return tb_true; -} -tb_bool_t tb_aicp_ssl_task(tb_aicp_ssl_ref_t ssl, tb_size_t delay, tb_aicp_ssl_task_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl && impl->aico && func, tb_false); - - // save func - impl->func.task.func = func; - impl->func.task.priv = priv; - impl->post.delay = delay; - - // run task - return tb_aico_task_run(impl->aico, delay, tb_aicp_ssl_done_task, impl); -} -tb_bool_t tb_aicp_ssl_open_read(tb_aicp_ssl_ref_t ssl, tb_byte_t* data, tb_size_t size, tb_aicp_ssl_read_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl && data && size && func, tb_false); - - // not opened? open it first - if (TB_STATE_CLOSED == tb_atomic_get(&impl->state)) - { - impl->open_and.read.func = func; - impl->open_and.read.data = data; - impl->open_and.read.size = size; - impl->open_and.read.priv = priv; - return tb_aicp_ssl_open(ssl, tb_aicp_ssl_open_and_read, &impl->open_and.read); - } - - // read it - return tb_aicp_ssl_read(ssl, data, size, func, priv); -} -tb_bool_t tb_aicp_ssl_open_writ(tb_aicp_ssl_ref_t ssl, tb_byte_t const* data, tb_size_t size, tb_aicp_ssl_writ_func_t func, tb_cpointer_t priv) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl && data && size && func, tb_false); - - // not opened? open it first - if (TB_STATE_CLOSED == tb_atomic_get(&impl->state)) - { - impl->open_and.writ.func = func; - impl->open_and.writ.data = data; - impl->open_and.writ.size = size; - impl->open_and.writ.priv = priv; - return tb_aicp_ssl_open(ssl, tb_aicp_ssl_open_and_writ, &impl->open_and.writ); - } - - // writ it - return tb_aicp_ssl_writ(ssl, data, size, func, priv); -} -tb_aicp_ref_t tb_aicp_ssl_aicp(tb_aicp_ssl_ref_t ssl) -{ - // check - tb_aicp_ssl_impl_t* impl = (tb_aicp_ssl_impl_t*)ssl; - tb_assert_and_check_return_val(impl, tb_null); - - // the aicp - return impl->aicp; -} - diff --git a/core/src/tbox/src/tbox/asio/deprecated/ssl.h b/core/src/tbox/src/tbox/asio/deprecated/ssl.h deleted file mode 100644 index b14a56df0..000000000 --- a/core/src/tbox/src/tbox/asio/deprecated/ssl.h +++ /dev/null @@ -1,287 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file ssl.h - * @ingroup asio - * - */ -#ifndef TB_ASIO_SSL_H -#define TB_ASIO_SSL_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "aicp.h" -#include "../../network/ssl.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the aicp ssl ref type -typedef __tb_typeref__(aicp_ssl); - -/*! the aicp ssl open func type - * - * @param ssl the ssl - * @param state the state - * @param priv the func private data - * - * @return tb_true: ok, tb_false: error, but not break aicp - */ -typedef tb_bool_t (*tb_aicp_ssl_open_func_t)(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_cpointer_t priv); - -/*! the aicp ssl clos func type - * - * @param ssl the ssl - * @param state the state - * @param priv the func private data - */ -typedef tb_void_t (*tb_aicp_ssl_clos_func_t)(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_cpointer_t priv); - -/*! the aicp ssl read func type - * - * @param ssl the ssl - * @param state the state - * @param data the readed data - * @param real the real size, maybe zero - * @param size the need size - * @param priv the func private data - * - * @return tb_true: ok and continue it if need, tb_false: break it, but not break aicp - */ -typedef tb_bool_t (*tb_aicp_ssl_read_func_t)(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_byte_t* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv); - -/*! the aicp ssl writ func type - * - * @param ssl the ssl - * @param state the state - * @param data the writed data - * @param real the real size, maybe zero - * @param size the need size - * @param priv the func private data - * - * @return tb_true: ok and continue it if need, tb_false: break it, but not break aicp - */ -typedef tb_bool_t (*tb_aicp_ssl_writ_func_t)(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_byte_t const* data, tb_size_t real, tb_size_t size, tb_cpointer_t priv); - -/*! the aicp ssl task func type - * - * @param ssl the ssl - * @param state the state - * @param delay the delay - * @param priv the func private data - * - * @return tb_true: ok, tb_false: error, but not break aicp - */ -typedef tb_bool_t (*tb_aicp_ssl_task_func_t)(tb_aicp_ssl_ref_t ssl, tb_size_t state, tb_size_t delay, tb_cpointer_t priv); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init the ssl - * - * @param aicp the aicp - * @param bserver is server endpoint? - * - * @return the ssl - */ -__tb_deprecated__ -tb_aicp_ssl_ref_t tb_aicp_ssl_init(tb_aicp_ref_t aicp, tb_bool_t bserver); - -/*! kill the ssl - * - * @param ssl the ssl - */ -__tb_deprecated__ -tb_void_t tb_aicp_ssl_kill(tb_aicp_ssl_ref_t ssl); - -/*! exit the ssl - * - * @param ssl the ssl - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_exit(tb_aicp_ssl_ref_t ssl); - -/*! set the ssl aico - * - * @param ssl the ssl - * @param aico the aico - */ -__tb_deprecated__ -tb_void_t tb_aicp_ssl_set_aico(tb_aicp_ssl_ref_t ssl, tb_aico_ref_t aico); - -/*! set the ssl timeout - * - * @param ssl the ssl - * @param timeout the ssl timeout, using the default timeout if be zero - */ -__tb_deprecated__ -tb_void_t tb_aicp_ssl_set_timeout(tb_aicp_ssl_ref_t ssl, tb_long_t timeout); - -/*! open the ssl - * - * @param ssl the ssl - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_open(tb_aicp_ssl_ref_t ssl, tb_aicp_ssl_open_func_t func, tb_cpointer_t priv); - -/*! close the ssl - * - * @param handle the ssl - * @param func the func - * @param priv the func private data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_clos(tb_aicp_ssl_ref_t ssl, tb_aicp_ssl_clos_func_t func, tb_cpointer_t priv); - -/*! try closing the ssl - * - * @param ssl the ssl - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_clos_try(tb_aicp_ssl_ref_t ssl); - -/*! read the ssl - * - * @param ssl the ssl - * @param data the read data - * @param size the read size - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_read(tb_aicp_ssl_ref_t ssl, tb_byte_t* data, tb_size_t size, tb_aicp_ssl_read_func_t func, tb_cpointer_t priv); - -/*! writ the ssl - * - * @param ssl the ssl - * @param data the data - * @param size the size - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_writ(tb_aicp_ssl_ref_t ssl, tb_byte_t const* data, tb_size_t size, tb_aicp_ssl_writ_func_t func, tb_cpointer_t priv); - -/*! read the ssl after the delay time - * - * @param ssl the ssl - * @param delay the delay time, ms - * @param data the read data - * @param size the read size - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_read_after(tb_aicp_ssl_ref_t ssl, tb_size_t delay, tb_byte_t* data, tb_size_t size, tb_aicp_ssl_read_func_t func, tb_cpointer_t priv); - -/*! writ the ssl after the delay time - * - * @param ssl the ssl - * @param delay the delay time, ms - * @param data the data - * @param size the size - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_writ_after(tb_aicp_ssl_ref_t ssl, tb_size_t delay, tb_byte_t const* data, tb_size_t size, tb_aicp_ssl_writ_func_t func, tb_cpointer_t priv); - -/*! task the ssl - * - * @param ssl the ssl - * @param delay the delay time, ms - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_task(tb_aicp_ssl_ref_t ssl, tb_size_t delay, tb_aicp_ssl_task_func_t func, tb_cpointer_t priv); - -/*! open and read the ssl, open it first if not opened - * - * @param ssl the ssl - * @param data the read data - * @param size the read size - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_open_read(tb_aicp_ssl_ref_t ssl, tb_byte_t* data, tb_size_t size, tb_aicp_ssl_read_func_t func, tb_cpointer_t priv); - -/*! open and writ the ssl, open it first if not opened - * - * @param ssl the ssl - * @param data the data - * @param size the size - * @param func the func - * @param priv the func data - * - * @return tb_true or tb_false - */ -__tb_deprecated__ -tb_bool_t tb_aicp_ssl_open_writ(tb_aicp_ssl_ref_t ssl, tb_byte_t const* data, tb_size_t size, tb_aicp_ssl_writ_func_t func, tb_cpointer_t priv); - -/*! the ssl aicp - * - * @param ssl the ssl - * - * @return the aicp - */ -__tb_deprecated__ -tb_aicp_ref_t tb_aicp_ssl_aicp(tb_aicp_ssl_ref_t ssl); - - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/asio/prefix.h b/core/src/tbox/src/tbox/asio/prefix.h deleted file mode 100644 index ee23c2646..000000000 --- a/core/src/tbox/src/tbox/asio/prefix.h +++ /dev/null @@ -1,33 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_ASIO_PREFIX_H -#define TB_ASIO_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" - -#endif diff --git a/core/src/tbox/src/tbox/container/element/prefix.h b/core/src/tbox/src/tbox/container/element/prefix.h index 7989dd5a6..27678adcb 100644 --- a/core/src/tbox/src/tbox/container/element/prefix.h +++ b/core/src/tbox/src/tbox/container/element/prefix.h @@ -33,7 +33,6 @@ #include "../../libc/libc.h" #include "../../utils/utils.h" #include "../../memory/memory.h" -#include "../../object/object.h" #include "../../stream/stream.h" #include "../../platform/platform.h" diff --git a/core/src/tbox/src/tbox/container/iterator/prefix.h b/core/src/tbox/src/tbox/container/iterator/prefix.h index c5e0f98d2..2ba954c74 100644 --- a/core/src/tbox/src/tbox/container/iterator/prefix.h +++ b/core/src/tbox/src/tbox/container/iterator/prefix.h @@ -33,7 +33,6 @@ #include "../../libc/libc.h" #include "../../utils/utils.h" #include "../../memory/memory.h" -#include "../../object/object.h" #include "../../platform/platform.h" diff --git a/core/src/tbox/src/tbox/coroutine/channel.c b/core/src/tbox/src/tbox/coroutine/channel.c deleted file mode 100644 index 1a1dd82a8..000000000 --- a/core/src/tbox/src/tbox/coroutine/channel.c +++ /dev/null @@ -1,487 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file channel.h - * @ingroup coroutine - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "channel" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "channel.h" -#include "coroutine.h" -#include "scheduler.h" -#include "impl/impl.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/* the channel queue type - * - * we do not use tb_circle_queue_t because it is too heavy - */ -typedef struct __tb_co_channel_queue_t -{ - // the data - tb_cpointer_t* data; - - // the head - tb_size_t head; - - // the tail - tb_size_t tail; - - // the maxn - tb_size_t maxn; - - // the size - tb_size_t size; - -}tb_co_channel_queue_t; - -// the coroutine channel type -typedef struct __tb_co_channel_t -{ - // the queue - tb_co_channel_queue_t queue; - - // the free function - tb_co_channel_free_func_t free; - - // the user private data - tb_cpointer_t priv; - - // the waiting send coroutines - tb_single_list_entry_head_t waiting_send; - - // the waiting recv coroutines - tb_single_list_entry_head_t waiting_recv; - -}tb_co_channel_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -static tb_bool_t tb_co_channel_send_resume(tb_co_channel_t* channel, tb_pointer_t* pdata) -{ - // check - tb_assert(channel); - - // resume the first waiting send coroutine and recv data - tb_bool_t ok = tb_false; - if (tb_single_list_entry_size(&channel->waiting_send)) - { - // get the next entry from head - tb_single_list_entry_ref_t entry = tb_single_list_entry_head(&channel->waiting_send); - tb_assert(entry); - - // remove it from the waiting send coroutines - tb_single_list_entry_remove_head(&channel->waiting_send); - - // get the waiting send coroutine - tb_coroutine_ref_t waiting = (tb_coroutine_ref_t)tb_single_list_entry(&channel->waiting_send, entry); - - // resume this coroutine and recv data - tb_pointer_t data = tb_coroutine_resume(waiting, tb_null); - - // save data - if (pdata) *pdata = data; - - // ok - ok = tb_true; - } - - // ok? - return ok; -} -static tb_void_t tb_co_channel_recv_resume(tb_co_channel_t* channel) -{ - // check - tb_assert(channel); - - // resume the first waiting recv coroutine - if (tb_single_list_entry_size(&channel->waiting_recv)) - { - // get the next entry from head - tb_single_list_entry_ref_t entry = tb_single_list_entry_head(&channel->waiting_recv); - tb_assert(entry); - - // remove it from the waiting recv coroutines - tb_single_list_entry_remove_head(&channel->waiting_recv); - - // get the waiting recv coroutine - tb_coroutine_ref_t waiting = (tb_coroutine_ref_t)tb_single_list_entry(&channel->waiting_recv, entry); - - // resume this coroutine - tb_coroutine_resume(waiting, tb_null); - } -} -static tb_void_t tb_co_channel_send_suspend(tb_co_channel_t* channel, tb_cpointer_t data) -{ - // check - tb_assert(channel); - - // get the running coroutine - tb_coroutine_t* running = (tb_coroutine_t*)tb_coroutine_self(); - tb_assert(running); - - // save this coroutine to the waiting send coroutines - tb_single_list_entry_insert_tail(&channel->waiting_send, &running->rs.single_entry); - - // send data and wait it - tb_coroutine_suspend(data); -} -static tb_void_t tb_co_channel_recv_suspend(tb_co_channel_t* channel) -{ - // check - tb_assert(channel); - - // get the running coroutine - tb_coroutine_t* running = (tb_coroutine_t*)tb_coroutine_self(); - tb_assert(running); - - // save this coroutine to the waiting recv coroutines - tb_single_list_entry_insert_tail(&channel->waiting_recv, &running->rs.single_entry); - - // wait data - tb_coroutine_suspend(tb_null); -} -static tb_void_t tb_co_channel_send_buffer(tb_co_channel_t* channel, tb_cpointer_t data) -{ - // check - tb_assert_and_check_return(channel && channel->queue.data); - - // done - do - { - // put data into queue if be not full - if (channel->queue.size + 1 < channel->queue.maxn) - { - // trace - tb_trace_d("send[%p]: put data(%p)", tb_coroutine_self(), data); - - // put data - channel->queue.data[channel->queue.tail] = data; - channel->queue.tail = (channel->queue.tail + 1) % channel->queue.maxn; - channel->queue.size++; - - // notify to recv data - tb_co_channel_recv_resume(channel); - - // send ok - break; - } - // wait it if be full - else - { - // trace - tb_trace_d("send[%p]: wait ..", tb_coroutine_self()); - - // wait send - tb_co_channel_send_suspend(channel, tb_null); - - // trace - tb_trace_d("send[%p]: wait ok", tb_coroutine_self()); - } - - } while (1); - - // trace - tb_trace_d("send[%p]: ok", tb_coroutine_self()); -} -static tb_pointer_t tb_co_channel_recv_buffer(tb_co_channel_t* channel) -{ - // check - tb_assert_and_check_return_val(channel && channel->queue.data, tb_null); - - // done - tb_pointer_t data = tb_null; - do - { - // recv data from channel if be not null - if (channel->queue.size) - { - // get data - data = (tb_pointer_t)channel->queue.data[channel->queue.head]; - - // pop data - channel->queue.head = (channel->queue.head + 1) % channel->queue.maxn; - channel->queue.size--; - - // trace - tb_trace_d("recv[%p]: get data(%p)", tb_coroutine_self(), data); - - // notify to send data - tb_co_channel_send_resume(channel, tb_null); - - // recv ok - break; - } - // wait it if be null - else - { - // trace - tb_trace_d("recv[%p]: wait ..", tb_coroutine_self()); - - // wait recv - tb_co_channel_recv_suspend(channel); - - // trace - tb_trace_d("recv[%p]: wait ok", tb_coroutine_self()); - } - - } while (1); - - // trace - tb_trace_d("recv[%p]: ok", tb_coroutine_self()); - - // get data - return data; -} -static tb_bool_t tb_co_channel_send_buffer_try(tb_co_channel_t* channel, tb_cpointer_t data) -{ - // check - tb_assert_and_check_return_val(channel && channel->queue.data, tb_false); - - // put data into queue if be not full - if (channel->queue.size + 1 < channel->queue.maxn) - { - // trace - tb_trace_d("send[%p]: put data(%p)", tb_coroutine_self(), data); - - // put data - channel->queue.data[channel->queue.tail] = data; - channel->queue.tail = (channel->queue.tail + 1) % channel->queue.maxn; - channel->queue.size++; - - // notify to recv data - tb_co_channel_recv_resume(channel); - - // send ok - return tb_true; - } - - // failed - return tb_false; -} -static tb_bool_t tb_co_channel_recv_buffer_try(tb_co_channel_t* channel, tb_pointer_t* pdata) -{ - // check - tb_assert_and_check_return_val(channel && channel->queue.data && pdata, tb_false); - - // recv data from channel if be not null - if (channel->queue.size) - { - // get data - *pdata = (tb_pointer_t)channel->queue.data[channel->queue.head]; - - // pop data - channel->queue.head = (channel->queue.head + 1) % channel->queue.maxn; - channel->queue.size--; - - // trace - tb_trace_d("recv[%p]: get data(%p)", tb_coroutine_self(), *pdata); - - // notify to send data - tb_co_channel_send_resume(channel, tb_null); - - // recv ok - return tb_true; - } - - // failed - return tb_false; -} -static tb_void_t tb_co_channel_send_buffer0(tb_co_channel_t* channel, tb_cpointer_t data) -{ - // check - tb_assert(channel); - - // resume one waiting recv coroutine - tb_co_channel_recv_resume(channel); - - // send data and wait it - tb_co_channel_send_suspend(channel, data); -} -static tb_pointer_t tb_co_channel_recv_buffer0(tb_co_channel_t* channel) -{ - // check - tb_assert(channel); - - // done - tb_pointer_t data = tb_null; - do - { - // resume the first waiting send coroutine and recv data - if (tb_co_channel_send_resume(channel, &data)) - { - // recv ok - break; - } - // no data? - else - { - // wait data - tb_co_channel_recv_suspend(channel); - } - - } while (1); - - // ok? - return data; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_co_channel_ref_t tb_co_channel_init(tb_size_t size, tb_co_channel_free_func_t free, tb_cpointer_t priv) -{ - // done - tb_bool_t ok = tb_false; - tb_co_channel_t* channel = tb_null; - do - { - // make channel - channel = tb_malloc0_type(tb_co_channel_t); - tb_assert_and_check_break(channel); - - // init waiting send coroutines - tb_single_list_entry_init(&channel->waiting_send, tb_coroutine_t, rs.single_entry, tb_null); - - // init waiting recv coroutines - tb_single_list_entry_init(&channel->waiting_recv, tb_coroutine_t, rs.single_entry, tb_null); - - // init free function and data - channel->free = free; - channel->priv = priv; - - // with buffer? - if (size) - { - // init maxn, + tail - channel->queue.maxn = size + 1; - - // make data - channel->queue.data = tb_nalloc_type(channel->queue.maxn, tb_cpointer_t); - tb_assert_and_check_break(channel->queue.data); - } - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (channel) tb_co_channel_exit((tb_co_channel_ref_t)channel); - channel = tb_null; - } - - // ok? - return (tb_co_channel_ref_t)channel; -} -tb_void_t tb_co_channel_exit(tb_co_channel_ref_t self) -{ - // check - tb_co_channel_t* channel = (tb_co_channel_t*)self; - tb_assert_and_check_return(channel); - - // exit queue - if (channel->queue.data) - { - // free data - if (channel->free) - { - tb_size_t head = channel->queue.head; - tb_size_t maxn = channel->queue.maxn; - tb_size_t size = channel->queue.size; - while (size--) - { - channel->free((tb_pointer_t)channel->queue.data[head], channel->priv); - head = (head + 1) % maxn; - } - } - - // free it - tb_free(channel->queue.data); - } - channel->queue.data = tb_null; - channel->queue.size = 0; - - // check waiting coroutines - tb_assert(!tb_single_list_entry_size(&channel->waiting_send)); - tb_assert(!tb_single_list_entry_size(&channel->waiting_recv)); - - // exit waiting coroutines - tb_single_list_entry_exit(&channel->waiting_send); - tb_single_list_entry_exit(&channel->waiting_recv); - - // exit the channel - tb_free(channel); -} -tb_void_t tb_co_channel_send(tb_co_channel_ref_t self, tb_cpointer_t data) -{ - // check - tb_co_channel_t* channel = (tb_co_channel_t*)self; - tb_assert_and_check_return(channel); - - // send it - if (channel->queue.data) tb_co_channel_send_buffer(channel, data); - else tb_co_channel_send_buffer0(channel, data); -} -tb_pointer_t tb_co_channel_recv(tb_co_channel_ref_t self) -{ - // check - tb_co_channel_t* channel = (tb_co_channel_t*)self; - tb_assert_and_check_return_val(channel, tb_null); - - // recv it - return channel->queue.data? tb_co_channel_recv_buffer(channel) : tb_co_channel_recv_buffer0(channel); -} -tb_bool_t tb_co_channel_send_try(tb_co_channel_ref_t self, tb_cpointer_t data) -{ - // check - tb_co_channel_t* channel = (tb_co_channel_t*)self; - tb_assert_and_check_return_val(channel, tb_false); - - // try sending it - return channel->queue.data? tb_co_channel_send_buffer_try(channel, data) : tb_false; -} -tb_bool_t tb_co_channel_recv_try(tb_co_channel_ref_t self, tb_pointer_t* pdata) -{ - // check - tb_co_channel_t* channel = (tb_co_channel_t*)self; - tb_assert_and_check_return_val(channel && pdata, tb_false); - - // try recving it - return channel->queue.data? tb_co_channel_recv_buffer_try(channel, pdata) : tb_false; -} - diff --git a/core/src/tbox/src/tbox/coroutine/channel.h b/core/src/tbox/src/tbox/coroutine/channel.h deleted file mode 100644 index c5b6c0749..000000000 --- a/core/src/tbox/src/tbox/coroutine/channel.h +++ /dev/null @@ -1,120 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file channel.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_CHANNEL_H -#define TB_COROUTINE_CHANNEL_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "../container/container.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the coroutine channel ref type -typedef __tb_typeref__(co_channel); - -/*! the free function type - * - * @param data the channel data - * @param priv the user private data - */ -typedef tb_void_t (*tb_co_channel_free_func_t)(tb_pointer_t data, tb_cpointer_t priv); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init channel - * - * @param size the buffer size, 0: no buffer - * @param free the free function - * @param priv the user private data - * - * @return the channel - */ -tb_co_channel_ref_t tb_co_channel_init(tb_size_t size, tb_co_channel_free_func_t free, tb_cpointer_t priv); - -/*! exit channel - * - * @param channel the channel - */ -tb_void_t tb_co_channel_exit(tb_co_channel_ref_t channel); - -/*! send data into channel - * - * the current coroutine will be suspend if this channel is full - * - * @param channel the channel - * @param data the channel data - */ -tb_void_t tb_co_channel_send(tb_co_channel_ref_t channel, tb_cpointer_t data); - -/*! recv data from channel - * - * the current coroutine will be suspend if no data - * - * @param channel the channel - * - * @return the channel data - */ -tb_pointer_t tb_co_channel_recv(tb_co_channel_ref_t channel); - -/*! try sending data into channel only with buffer - * - * the current coroutine will be suspend if this channel is full - * - * @param channel the channel - * @param data the channel data - * - * @return tb_true or tb_false - */ -tb_bool_t tb_co_channel_send_try(tb_co_channel_ref_t channel, tb_cpointer_t data); - -/*! try recving data from channel only with buffer - * - * the current coroutine will be suspend if no data - * - * @param channel the channel - * @param pdata the channel data pointer - * - * @return tb_true or tb_false - */ -tb_bool_t tb_co_channel_recv_try(tb_co_channel_ref_t channel, tb_pointer_t* pdata); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/coroutine.c b/core/src/tbox/src/tbox/coroutine/coroutine.c deleted file mode 100644 index b5b863ea3..000000000 --- a/core/src/tbox/src/tbox/coroutine/coroutine.c +++ /dev/null @@ -1,99 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file coroutine.h - * @ingroup coroutine - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "coroutine" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "coroutine.h" -#include "scheduler.h" -#include "impl/impl.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_bool_t tb_coroutine_start(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize) -{ - // check - tb_assert_and_check_return_val(func, tb_false); - - // start it - return tb_co_scheduler_start((tb_co_scheduler_t*)scheduler, func, priv, stacksize); -} -tb_bool_t tb_coroutine_yield() -{ - // get current scheduler - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); - - // yield the current coroutine - return scheduler? tb_co_scheduler_yield(scheduler) : tb_false; -} -tb_pointer_t tb_coroutine_resume(tb_coroutine_ref_t coroutine, tb_cpointer_t priv) -{ - // get current scheduler - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); - - // resume the given coroutine - return scheduler? tb_co_scheduler_resume(scheduler, (tb_coroutine_t*)coroutine, priv) : tb_null; -} -tb_pointer_t tb_coroutine_suspend(tb_cpointer_t priv) -{ - // get current scheduler - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); - - // suspend the current coroutine - return scheduler? tb_co_scheduler_suspend(scheduler, priv) : tb_null; -} -tb_pointer_t tb_coroutine_sleep(tb_long_t interval) -{ - // get current scheduler - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); - - // sleep the current coroutine - return scheduler? tb_co_scheduler_sleep(scheduler, interval) : tb_null; -} -tb_long_t tb_coroutine_waitio(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout) -{ - // get current scheduler - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); - - // wait events - return scheduler? tb_co_scheduler_wait(scheduler, sock, events, timeout) : -1; -} -tb_coroutine_ref_t tb_coroutine_self() -{ - // get coroutine - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); - - // get running coroutine - return scheduler? (tb_coroutine_ref_t)tb_co_scheduler_running(scheduler) : tb_null; -} - diff --git a/core/src/tbox/src/tbox/coroutine/coroutine.h b/core/src/tbox/src/tbox/coroutine/coroutine.h deleted file mode 100644 index 7bdc33d82..000000000 --- a/core/src/tbox/src/tbox/coroutine/coroutine.h +++ /dev/null @@ -1,120 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file coroutine.h - * @defgroup coroutine - * - */ -#ifndef TB_COROUTINE_H -#define TB_COROUTINE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "lock.h" -#include "channel.h" -#include "semaphore.h" -#include "scheduler.h" -#include "stackless/stackless.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the coroutine ref type -typedef __tb_typeref__(coroutine); - -/// the coroutine function type -typedef tb_void_t (*tb_coroutine_func_t)(tb_cpointer_t priv); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! start coroutine - * - * @param scheduler the scheduler, uses the current scheduler if be null - * @param func the coroutine function - * @param priv the passed user private data as the argument of function - * @param stacksize the stack size - * - * @return tb_true or tb_false - */ -tb_bool_t tb_coroutine_start(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize); - -/*! yield the current coroutine - * - * @return tb_true(yield ok) or tb_false(yield failed, no more coroutines) - */ -tb_bool_t tb_coroutine_yield(tb_noarg_t); - -/*! resume the given coroutine (suspended) - * - * @param coroutine the suspended coroutine - * @param priv the user private data as the return value of suspend() or sleep() - * - * @return the user private data from suspend(priv) - */ -tb_pointer_t tb_coroutine_resume(tb_coroutine_ref_t coroutine, tb_cpointer_t priv); - -/*! suspend the current coroutine - * - * @param priv the user private data as the return value of resume() - * - * @return the user private data from resume(priv) - */ -tb_pointer_t tb_coroutine_suspend(tb_cpointer_t priv); - -/*! sleep some times (ms) - * - * @param interval the interval (ms), infinity: -1 - * - * @return the user private data from resume(priv) - */ -tb_pointer_t tb_coroutine_sleep(tb_long_t interval); - -/*! wait io events - * - * @param sock the socket - * @param events the waited events, will remove this socket from io scheduler if be TB_SOCKET_EVENT_NONE - * @param timeout the timeout, infinity: -1 - * - * @return > 0: the events, 0: timeout, -1: failed - */ -tb_long_t tb_coroutine_waitio(tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout); - -/*! get the current coroutine - * - * @return the current coroutine - */ -tb_coroutine_ref_t tb_coroutine_self(tb_noarg_t); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/coroutine.c b/core/src/tbox/src/tbox/coroutine/impl/coroutine.c deleted file mode 100644 index 3341d780c..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/coroutine.c +++ /dev/null @@ -1,269 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file coroutine.h - * @ingroup coroutine - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "coroutine" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "coroutine.h" -#include "scheduler.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the stack guard magic -#define TB_COROUTINE_STACK_GUARD (0xbeef) - -// the default stack size -#define TB_COROUTINE_STACK_DEFSIZE (8192 << 1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_void_t tb_coroutine_entry(tb_context_from_t from) -{ - // get the from-coroutine - tb_coroutine_t* coroutine_from = (tb_coroutine_t*)from.priv; - tb_assert(coroutine_from && from.context); - - // update the context - coroutine_from->context = from.context; - tb_assert(from.context); - - // get the current coroutine - tb_coroutine_t* coroutine = (tb_coroutine_t*)tb_coroutine_self(); - tb_assert(coroutine); - -#ifdef __tb_debug__ - // check it - tb_coroutine_check(coroutine); -#endif - - // trace - tb_trace_d("entry: %p stack: %p - %p from coroutine(%p)", coroutine, coroutine->stackbase - coroutine->stacksize, coroutine->stackbase, coroutine_from); - - // get function and private data - tb_coroutine_func_t func = coroutine->rs.func.func; - tb_cpointer_t priv = coroutine->rs.func.priv; - tb_assert(func); - - // reset rs data first for waiting io - tb_memset(&coroutine->rs, 0, sizeof(coroutine->rs)); - - // call the coroutine function - func(priv); - - // finish the current coroutine and switch to the other coroutine - tb_co_scheduler_finish((tb_co_scheduler_t*)tb_co_scheduler_self()); -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_coroutine_t* tb_coroutine_init(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize) -{ - // check - tb_assert_and_check_return_val(scheduler && func, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_coroutine_t* coroutine = tb_null; - do - { - // init stack size - if (!stacksize) stacksize = TB_COROUTINE_STACK_DEFSIZE; - -#ifdef __tb_debug__ - // patch debug stack size for (assert, trace ..) - stacksize <<= 1; -#endif - - /* make coroutine - * - * TODO: - * - * - segment stack - * - * ----------------------------------------------- - * | coroutine | guard | ... stacksize ... | guard | - * ----------------------------------------------- - */ - coroutine = (tb_coroutine_t*)tb_malloc_bytes(sizeof(tb_coroutine_t) + stacksize + sizeof(tb_uint16_t)); - tb_assert_and_check_break(coroutine); - - // save scheduler - coroutine->scheduler = scheduler; - - // init stack - coroutine->stackbase = (tb_byte_t*)&(coroutine[1]) + stacksize; - coroutine->stacksize = stacksize; - - // fill guard - coroutine->guard = TB_COROUTINE_STACK_GUARD; - tb_bits_set_u16_ne(coroutine->stackbase, TB_COROUTINE_STACK_GUARD); - - // init function and user private data - coroutine->rs.func.func = func; - coroutine->rs.func.priv = priv; - - // make context - coroutine->context = tb_context_make(coroutine->stackbase - stacksize, stacksize, tb_coroutine_entry); - tb_assert_and_check_break(coroutine->context); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (coroutine) tb_coroutine_exit(coroutine); - coroutine = tb_null; - } - - // trace - tb_trace_d("init %p", coroutine); - - // ok? - return coroutine; -} -tb_coroutine_t* tb_coroutine_reinit(tb_coroutine_t* coroutine, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize) -{ - // check - tb_assert_and_check_return_val(coroutine && func, tb_null); - - // done - tb_bool_t ok = tb_false; - do - { - // init stack size - if (!stacksize) stacksize = TB_COROUTINE_STACK_DEFSIZE; - -#ifdef __tb_debug__ - // patch debug stack size for (assert, trace ..) - stacksize <<= 1; - - // check coroutine - tb_coroutine_check(coroutine); -#endif - - // remake coroutine - if (stacksize > coroutine->stacksize) - coroutine = (tb_coroutine_t*)tb_ralloc_bytes(coroutine, sizeof(tb_coroutine_t) + stacksize + sizeof(tb_uint16_t)); - else stacksize = coroutine->stacksize; - tb_assert_and_check_break(coroutine && coroutine->scheduler); - - // init stack - coroutine->stackbase = (tb_byte_t*)&(coroutine[1]) + stacksize; - coroutine->stacksize = stacksize; - - // fill guard - coroutine->guard = TB_COROUTINE_STACK_GUARD; - tb_bits_set_u16_ne(coroutine->stackbase, TB_COROUTINE_STACK_GUARD); - - // init function and user private data - coroutine->rs.func.func = func; - coroutine->rs.func.priv = priv; - - // make context - coroutine->context = tb_context_make(coroutine->stackbase - stacksize, stacksize, tb_coroutine_entry); - tb_assert_and_check_break(coroutine->context); - - // ok - ok = tb_true; - - } while (0); - - // failed? reset it - if (!ok) coroutine = tb_null; - - // trace - tb_trace_d("reinit %p", coroutine); - - // ok? - return coroutine; -} -tb_void_t tb_coroutine_exit(tb_coroutine_t* coroutine) -{ - // check - tb_assert_and_check_return(coroutine); - - // trace - tb_trace_d("exit: %p", coroutine); - -#ifdef __tb_debug__ - // check it - tb_coroutine_check(coroutine); -#endif - - // exit it - tb_free(coroutine); -} -#ifdef __tb_debug__ -tb_void_t tb_coroutine_check(tb_coroutine_t* coroutine) -{ - // check - tb_assert(coroutine && coroutine->context); - - // this coroutine is original for scheduler? - tb_check_return(!tb_coroutine_is_original(coroutine)); - - // check stack underflow - if (coroutine->guard != TB_COROUTINE_STACK_GUARD) - { - // trace - tb_trace_e("this coroutine stack is underflow!"); - - // dump stack - tb_dump_data(coroutine->stackbase - coroutine->stacksize, coroutine->stacksize); - - // abort - tb_abort(); - } - - // check stack overflow - if (tb_bits_get_u16_ne(coroutine->stackbase) != TB_COROUTINE_STACK_GUARD) - { - // trace - tb_trace_e("this coroutine stack is overflow!"); - - // dump stack - tb_dump_data(coroutine->stackbase - coroutine->stacksize, coroutine->stacksize); - - // abort - tb_abort(); - } -} -#endif - diff --git a/core/src/tbox/src/tbox/coroutine/impl/coroutine.h b/core/src/tbox/src/tbox/coroutine/impl/coroutine.h deleted file mode 100644 index ae27d74bf..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/coroutine.h +++ /dev/null @@ -1,179 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file coroutine.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_IMPL_COROUTINE_H -#define TB_COROUTINE_IMPL_COROUTINE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// get scheduler -#define tb_coroutine_scheduler(coroutine) ((coroutine)->scheduler) - -// is original? -#define tb_coroutine_is_original(coroutine) ((coroutine)->scheduler == (tb_co_scheduler_ref_t)(coroutine)) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the coroutine function type -typedef struct __tb_coroutine_rs_func_t -{ - // the function - tb_coroutine_func_t func; - - // the user private data as the argument of function - tb_cpointer_t priv; - -}tb_coroutine_rs_func_t; - -// the coroutine wait type -typedef struct __tb_coroutine_rs_wait_t -{ - /* the timer task pointer for ltimer or timer - * - * for ltimer: task - * for timer: task & 0x1 - */ - tb_cpointer_t task; - - // the socket - tb_socket_ref_t sock; - - // the waiting events - tb_uint16_t events : 6; - - // the cached events - tb_uint16_t events_cache : 6; - - // is waiting? - tb_uint16_t waiting : 1; - -}tb_coroutine_rs_wait_t; - -// the coroutine type -typedef struct __tb_coroutine_t -{ - /* the list entry for ready, suspend and dead lists - * - * be placed in the head for optimization - */ - tb_list_entry_t entry; - - // the scheduler - tb_co_scheduler_ref_t scheduler; - - // the context - tb_context_ref_t context; - - // the stack base (top) - tb_byte_t* stackbase; - - // the stack size - tb_size_t stacksize; - - // the passed user private data between priv = resume(priv) and priv = suspend(priv) - tb_cpointer_t rs_priv; - - // the passed private data between resume() and suspend() - union - { - // the function - tb_coroutine_rs_func_t func; - - // the arguments for wait() - tb_coroutine_rs_wait_t wait; - - // the list entry - tb_list_entry_t entry; - - // the single entry - tb_single_list_entry_t single_entry; - - } rs; - - // the guard - tb_uint16_t guard; - -}tb_coroutine_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* init coroutine - * - * @param scheduler the scheduler - * @param func the coroutine function - * @param priv the passed user private data as the argument of function - * @param stacksize the stack size, uses the default stack size if be zero - * - * @return the coroutine - */ -tb_coroutine_t* tb_coroutine_init(tb_co_scheduler_ref_t scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize); - -/* reinit the given coroutine - * - * @param coroutine the coroutine - * @param func the coroutine function - * @param priv the passed user private data as the argument of function - * @param stacksize the stack size, uses the default stack size if be zero - * - * @return the coroutine - */ -tb_coroutine_t* tb_coroutine_reinit(tb_coroutine_t* coroutine, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize); - -/* exit coroutine - * - * @param coroutine the coroutine - */ -tb_void_t tb_coroutine_exit(tb_coroutine_t* coroutine); - -#ifdef __tb_debug__ -/* check coroutine - * - * @param coroutine the coroutine - */ -tb_void_t tb_coroutine_check(tb_coroutine_t* coroutine); -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/impl.h b/core/src/tbox/src/tbox/coroutine/impl/impl.h deleted file mode 100644 index e3aeb366e..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/impl.h +++ /dev/null @@ -1,37 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file impl.h - * - */ -#ifndef TB_COROUTINE_IMPL_H -#define TB_COROUTINE_IMPL_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "coroutine.h" -#include "scheduler.h" -#include "scheduler_io.h" -#include "stackless/stackless.h" - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/prefix.h b/core/src/tbox/src/tbox/coroutine/impl/prefix.h deleted file mode 100644 index bc6835ca4..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/prefix.h +++ /dev/null @@ -1,39 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_COROUTINE_IMPL_PREFIX_H -#define TB_COROUTINE_IMPL_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../coroutine.h" -#include "../../libc/libc.h" -#include "../../utils/utils.h" -#include "../../platform/platform.h" -#include "../../container/container.h" - - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/scheduler.c b/core/src/tbox/src/tbox/coroutine/impl/scheduler.c deleted file mode 100644 index 0653ca00a..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/scheduler.c +++ /dev/null @@ -1,383 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler.c - * @ingroup coroutine - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "scheduler" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "scheduler.h" -#include "coroutine.h" -#include "scheduler_io.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the dead cache maximum count -#ifdef __tb_small__ -# define TB_SCHEDULER_DEAD_CACHE_MAXN (64) -#else -# define TB_SCHEDULER_DEAD_CACHE_MAXN (256) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -static __tb_inline__ tb_bool_t tb_co_scheduler_need_io(tb_co_scheduler_t* scheduler) -{ - // check - tb_assert(scheduler); - - // init io scheduler first - if (!scheduler->scheduler_io) scheduler->scheduler_io = tb_co_scheduler_io_init(scheduler); - tb_assert(scheduler->scheduler_io); - - // ok? - return scheduler->scheduler_io != tb_null; -} -static tb_void_t tb_co_scheduler_make_dead(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine) -{ - // check - tb_assert(scheduler && coroutine); - - // cannot be original coroutine - tb_assert(!tb_coroutine_is_original(coroutine)); - - // remove this coroutine from the ready coroutines - tb_list_entry_remove(&scheduler->coroutines_ready, (tb_list_entry_ref_t)coroutine); - - // append this coroutine to dead coroutines - tb_list_entry_insert_tail(&scheduler->coroutines_dead, (tb_list_entry_ref_t)coroutine); -} -static tb_void_t tb_co_scheduler_make_ready(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine) -{ - // check - tb_assert(scheduler && coroutine); - - // insert this coroutine to ready coroutines - if (__tb_unlikely__(tb_coroutine_is_original(scheduler->running))) - { - // .. last -> coroutine(inserted) - tb_list_entry_insert_tail(&scheduler->coroutines_ready, (tb_list_entry_ref_t)coroutine); - } - else - { - // .. -> coroutine(inserted) -> running -> .. - tb_list_entry_insert_prev(&scheduler->coroutines_ready, (tb_list_entry_ref_t)scheduler->running, (tb_list_entry_ref_t)coroutine); - } -} -static tb_void_t tb_co_scheduler_make_suspend(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine) -{ - // check - tb_assert(scheduler && coroutine); - - // cannot be original coroutine - tb_assert(!tb_coroutine_is_original(coroutine)); - - // remove this coroutine from the ready coroutines - tb_list_entry_remove(&scheduler->coroutines_ready, (tb_list_entry_ref_t)coroutine); - - // append this coroutine to suspend coroutines - tb_list_entry_insert_tail(&scheduler->coroutines_suspend, (tb_list_entry_ref_t)coroutine); -} -static __tb_inline__ tb_coroutine_t* tb_co_scheduler_next_ready(tb_co_scheduler_t* scheduler) -{ - // check - tb_assert(scheduler && scheduler->running && tb_list_entry_size(&scheduler->coroutines_ready)); - - // get the next entry - tb_list_entry_ref_t entry_next = tb_list_entry_next((tb_list_entry_ref_t)scheduler->running); - tb_assert(entry_next); - - // is list header? skip it and get the first entry - if (entry_next == (tb_list_entry_ref_t)&scheduler->coroutines_ready) - entry_next = tb_list_entry_next(entry_next); - - // get the next ready coroutine - return (tb_coroutine_t*)tb_list_entry0(entry_next); -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_bool_t tb_co_scheduler_start(tb_co_scheduler_t* scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize) -{ - // check - tb_assert(func); - - // done - tb_bool_t ok = tb_false; - tb_coroutine_t* coroutine = tb_null; - do - { - // trace - tb_trace_d("start .."); - - // uses the current scheduler if be null - if (!scheduler) scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); - tb_assert_and_check_break(scheduler); - - // have been stopped? do not continue to start new coroutines - tb_check_break(!scheduler->stopped); - - // reuses dead coroutines in init function - if (tb_list_entry_size(&scheduler->coroutines_dead)) - { - // get the next entry from head - tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead); - tb_assert_and_check_break(entry); - - // remove it from the ready coroutines - tb_list_entry_remove_head(&scheduler->coroutines_dead); - - // get the dead coroutine - tb_coroutine_t* coroutine_dead = (tb_coroutine_t*)tb_list_entry0(entry); - - // reinit this coroutine - coroutine = tb_coroutine_reinit(coroutine_dead, func, priv, stacksize); - - // failed? exit this coroutine - if (!coroutine) tb_coroutine_exit(coroutine_dead); - } - - // init coroutine - if (!coroutine) coroutine = tb_coroutine_init((tb_co_scheduler_ref_t)scheduler, func, priv, stacksize); - tb_assert_and_check_break(coroutine); - - // ready coroutine - tb_co_scheduler_make_ready(scheduler, coroutine); - - // the dead coroutines is too much? free some coroutines - while (tb_list_entry_size(&scheduler->coroutines_dead) > TB_SCHEDULER_DEAD_CACHE_MAXN) - { - // get the next entry from head - tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead); - tb_assert(entry); - - // remove it from the ready coroutines - tb_list_entry_remove_head(&scheduler->coroutines_dead); - - // exit this coroutine - tb_coroutine_exit((tb_coroutine_t*)tb_list_entry0(entry)); - } - - // ok - ok = tb_true; - - } while (0); - - // trace - tb_trace_d("start %s", ok? "ok" : "no"); - - // ok? - return ok; -} -tb_bool_t tb_co_scheduler_yield(tb_co_scheduler_t* scheduler) -{ - // check - tb_assert(scheduler && scheduler->running); - tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); - - // trace - tb_trace_d("yield coroutine(%p)", scheduler->running); - - // get the next ready coroutine - tb_coroutine_t* coroutine_next = tb_co_scheduler_next_ready(scheduler); - if (coroutine_next != scheduler->running) - { - // switch to the next coroutine - tb_co_scheduler_switch(scheduler, coroutine_next); - - // ok - return tb_true; - } - // no more coroutine (only running)? - else - { - // trace - tb_trace_d("continue to run current coroutine(%p)", tb_coroutine_self()); - - // check - tb_assert((tb_list_entry_ref_t)scheduler->running == tb_list_entry_head(&scheduler->coroutines_ready)); - } - - // return it directly and continue to run this coroutine - return tb_false; -} -tb_pointer_t tb_co_scheduler_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_cpointer_t priv) -{ - // check - tb_assert(scheduler && coroutine); - - // trace - tb_trace_d("resume coroutine(%p)", coroutine); - - // remove it from the suspend coroutines - tb_list_entry_remove(&scheduler->coroutines_suspend, (tb_list_entry_ref_t)coroutine); - - // get the passed private data from suspend(priv) - tb_pointer_t retval = (tb_pointer_t)coroutine->rs_priv; - - // pass the user private data to suspend() - coroutine->rs_priv = priv; - - // make it as ready - tb_co_scheduler_make_ready(scheduler, coroutine); - - // return it - return retval; -} -tb_pointer_t tb_co_scheduler_suspend(tb_co_scheduler_t* scheduler, tb_cpointer_t priv) -{ - // check - tb_assert(scheduler && scheduler->running); - tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); - - // have been stopped? return it directly - tb_check_return_val(!scheduler->stopped, tb_null); - - // trace - tb_trace_d("suspend coroutine(%p)", scheduler->running); - - // pass the private data to resume() first - scheduler->running->rs_priv = priv; - - // get the next ready coroutine first - tb_coroutine_t* coroutine_next = tb_co_scheduler_next_ready(scheduler); - - // make the running coroutine as suspend - tb_co_scheduler_make_suspend(scheduler, scheduler->running); - - // switch to next coroutine - if (coroutine_next != scheduler->running) tb_co_scheduler_switch(scheduler, coroutine_next); - // no more coroutine? - else - { - // trace - tb_trace_d("switch to original coroutine"); - - // switch to the original coroutine - tb_co_scheduler_switch(scheduler, &scheduler->original); - } - - // check - tb_assert(scheduler->running); - - // return the user private data from resume(priv) - return (tb_pointer_t)scheduler->running->rs_priv; -} -tb_void_t tb_co_scheduler_finish(tb_co_scheduler_t* scheduler) -{ - // check - tb_assert(scheduler && scheduler->running); - tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); - - // trace - tb_trace_d("finish coroutine(%p)", scheduler->running); - - // get the next ready coroutine first - tb_coroutine_t* coroutine_next = tb_co_scheduler_next_ready(scheduler); - - // make the running coroutine as dead - tb_co_scheduler_make_dead(scheduler, scheduler->running); - - // switch to next coroutine - if (coroutine_next != scheduler->running) tb_co_scheduler_switch(scheduler, coroutine_next); - // no more coroutine? - else - { - // trace - tb_trace_d("switch to original coroutine"); - - // switch to the original coroutine - tb_co_scheduler_switch(scheduler, &scheduler->original); - } -} -tb_pointer_t tb_co_scheduler_sleep(tb_co_scheduler_t* scheduler, tb_long_t interval) -{ - // check - tb_assert(scheduler && scheduler->running); - tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); - - // have been stopped? return it directly - tb_check_return_val(!scheduler->stopped, tb_null); - - // need io scheduler - if (!tb_co_scheduler_need_io(scheduler)) return tb_null; - - // sleep it - return tb_co_scheduler_io_sleep(scheduler->scheduler_io, interval); -} -tb_void_t tb_co_scheduler_switch(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine) -{ - // check - tb_assert(scheduler && scheduler->running); - tb_assert(coroutine && coroutine->context); - - // the current running coroutine - tb_coroutine_t* running = scheduler->running; - - // mark the given coroutine as running - scheduler->running = coroutine; - - // trace - tb_trace_d("switch to coroutine(%p) from coroutine(%p)", coroutine, running); - - // jump to the given coroutine - tb_context_from_t from = tb_context_jump(coroutine->context, running); - - // the from-coroutine - tb_coroutine_t* coroutine_from = (tb_coroutine_t*)from.priv; - tb_assert(coroutine_from && from.context); - -#ifdef __tb_debug__ - // check it - tb_coroutine_check(coroutine_from); -#endif - - // update the context - coroutine_from->context = from.context; -} -tb_long_t tb_co_scheduler_wait(tb_co_scheduler_t* scheduler, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout) -{ - // check - tb_assert(scheduler && scheduler->running); - tb_assert(scheduler->running == (tb_coroutine_t*)tb_coroutine_self()); - - // have been stopped? return it directly - tb_check_return_val(!scheduler->stopped, -1); - - // need io scheduler - if (!tb_co_scheduler_need_io(scheduler)) return -1; - - // sleep it - return tb_co_scheduler_io_wait(scheduler->scheduler_io, sock, events, timeout); -} diff --git a/core/src/tbox/src/tbox/coroutine/impl/scheduler.h b/core/src/tbox/src/tbox/coroutine/impl/scheduler.h deleted file mode 100644 index 98fa85d38..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/scheduler.h +++ /dev/null @@ -1,177 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_IMPL_SCHEDULER_H -#define TB_COROUTINE_IMPL_SCHEDULER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "coroutine.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// get the running coroutine -#define tb_co_scheduler_running(scheduler) ((scheduler)->running) - -// get the ready coroutines count -#define tb_co_scheduler_ready_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_ready) - -// get the suspended coroutines count -#define tb_co_scheduler_suspend_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_suspend) - -// get the io scheduler -#define tb_co_scheduler_io(scheduler) ((scheduler)->scheduler_io) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the io scheduler type -struct __tb_co_scheduler_io_t; - -// the scheduler type -typedef struct __tb_co_scheduler_t -{ - /* the original coroutine (in main loop) - * - * coroutine->scheduler == (tb_co_scheduler_ref_t)coroutine - */ - tb_coroutine_t original; - - // is stopped - tb_bool_t stopped; - - // the running coroutine - tb_coroutine_t* running; - - // the io scheduler - struct __tb_co_scheduler_io_t* scheduler_io; - - // the dead coroutines - tb_list_entry_head_t coroutines_dead; - - /* the ready coroutines - * - * ready: head -> ready -> .. -> running -> .. -> ready -> ..-> - * | | - * ---------------------------<----------------------- - */ - tb_list_entry_head_t coroutines_ready; - - // the suspend coroutines - tb_list_entry_head_t coroutines_suspend; - -}tb_co_scheduler_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* start the coroutine function - * - * @param scheduler the scheduler, uses the default scheduler if be null - * @param func the coroutine function - * @param priv the passed user private data as the argument of function - * @param stacksize the stack size - * - * @return tb_true or tb_false - */ -tb_bool_t tb_co_scheduler_start(tb_co_scheduler_t* scheduler, tb_coroutine_func_t func, tb_cpointer_t priv, tb_size_t stacksize); - -/* yield the current coroutine - * - * @param scheduler the scheduler - * - * @return tb_true(yield ok) or tb_false(yield failed, no more coroutines) - */ -tb_bool_t tb_co_scheduler_yield(tb_co_scheduler_t* scheduler); - -/*! resume the given coroutine (suspended) - * - * @param scheduler the scheduler - * @param coroutine the suspended coroutine - * @param priv the user private data as the return value of suspend() or sleep() - * - * @return the user private data from suspend(priv) - */ -tb_pointer_t tb_co_scheduler_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_cpointer_t priv); - -/*! suspend the current coroutine - * - * @param scheduler the scheduler - * @param priv the user private data as the return value of resume() - * - * @return the user private data from resume(priv) - */ -tb_pointer_t tb_co_scheduler_suspend(tb_co_scheduler_t* scheduler, tb_cpointer_t priv); - -/* finish the current coroutine - * - * @param scheduler the scheduler - */ -tb_void_t tb_co_scheduler_finish(tb_co_scheduler_t* scheduler); - -/* sleep the current coroutine - * - * @param scheduler the scheduler - * @param interval the interval (ms), infinity: -1 - * - * @return the user private data from resume(priv) - */ -tb_pointer_t tb_co_scheduler_sleep(tb_co_scheduler_t* scheduler, tb_long_t interval); - -/* switch to the given coroutine - * - * @param scheduler the scheduler - * @param coroutine the coroutine - */ -tb_void_t tb_co_scheduler_switch(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine); - -/*! wait io events - * - * @param scheduler the scheduler - * @param sock the socket - * @param events the waited events - * @param timeout the timeout, infinity: -1 - * - * @return > 0: the events, 0: timeout, -1: failed - */ -tb_long_t tb_co_scheduler_wait(tb_co_scheduler_t* scheduler, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.c b/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.c deleted file mode 100644 index 35d6d178d..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.c +++ /dev/null @@ -1,461 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler_io.c - * @ingroup coroutine - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "scheduler_io" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "scheduler_io.h" -#include "coroutine.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the ltimer grow -#ifdef __tb_small__ -# define TB_SCHEDULER_IO_LTIMER_GROW (64) -#else -# define TB_SCHEDULER_IO_LTIMER_GROW (4096) -#endif - -// the timer grow -#define TB_SCHEDULER_IO_TIMER_GROW (TB_SCHEDULER_IO_LTIMER_GROW >> 4) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -static tb_void_t tb_co_scheduler_io_resume(tb_co_scheduler_t* scheduler, tb_coroutine_t* coroutine, tb_cpointer_t priv) -{ - // exists the timer task? remove it - tb_cpointer_t task = coroutine->rs.wait.task; - if (task) - { - // get io scheduler - tb_co_scheduler_io_ref_t scheduler_io = tb_co_scheduler_io(scheduler); - tb_assert(scheduler_io && scheduler_io->poller); - - // is high-precision timer? - tb_size_t is_timer = (tb_size_t)(task) & 0x1; - - // check - tb_assert((tb_size_t)task & (tb_size_t)~0x1); - - // remove the timer task - if (__tb_unlikely__(is_timer)) tb_timer_task_exit(scheduler_io->timer, (tb_timer_task_ref_t)((tb_size_t)task & (tb_size_t)~0x1)); - else tb_ltimer_task_exit(scheduler_io->ltimer, (tb_ltimer_task_ref_t)task); - coroutine->rs.wait.task = tb_null; - } - - // clear waiting state - coroutine->rs.wait.waiting = 0; - - // resume the coroutine - tb_co_scheduler_resume(scheduler, coroutine, priv); -} -static tb_void_t tb_co_scheduler_io_timeout(tb_bool_t killed, tb_cpointer_t priv) -{ - // check - tb_coroutine_t* coroutine = (tb_coroutine_t*)priv; - tb_assert(coroutine); - - // get scheduler - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_coroutine_scheduler(coroutine); - tb_assert(scheduler); - - // trace - tb_trace_d("coroutine(%p): timer %s", coroutine, killed? "killed" : "timeout"); - - // resume the coroutine - tb_co_scheduler_io_resume(scheduler, coroutine, tb_null); -} -static tb_void_t tb_co_scheduler_io_events(tb_poller_ref_t poller, tb_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv) -{ - // check - tb_coroutine_t* coroutine = (tb_coroutine_t*)priv; - tb_assert(coroutine && poller && sock && priv); - - // get scheduler - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_coroutine_scheduler(coroutine); - tb_assert(scheduler); - - // trace - tb_trace_d("coroutine(%p): socket: %p, events %lu", coroutine, sock, events); - - // waiting now? - if (coroutine->rs.wait.waiting) - { - // eof for edge trigger? - if (events & TB_POLLER_EVENT_EOF) - { - // cache this eof as next recv/send event - events &= ~TB_POLLER_EVENT_EOF; - coroutine->rs.wait.events_cache |= coroutine->rs.wait.events; - } - - // resume the coroutine and pass the events to suspend() - tb_co_scheduler_io_resume(scheduler, coroutine, (tb_cpointer_t)events); - } - // cache this events - else coroutine->rs.wait.events_cache = events; -} -static tb_bool_t tb_co_scheduler_io_timer_spak(tb_co_scheduler_io_ref_t scheduler_io) -{ - // check - tb_assert(scheduler_io && scheduler_io->timer && scheduler_io->ltimer); - - // spak ctime - tb_cache_time_spak(); - - // spak timer - if (!tb_timer_spak(scheduler_io->timer)) return tb_false; - - // spak ltimer - if (!tb_ltimer_spak(scheduler_io->ltimer)) return tb_false; - - // pk - return tb_true; -} -static tb_void_t tb_co_scheduler_io_loop(tb_cpointer_t priv) -{ - // check - tb_co_scheduler_io_ref_t scheduler_io = (tb_co_scheduler_io_ref_t)priv; - tb_assert_and_check_return(scheduler_io && scheduler_io->timer && scheduler_io->ltimer); - - // the scheduler - tb_co_scheduler_t* scheduler = scheduler_io->scheduler; - tb_assert_and_check_return(scheduler); - - // the poller - tb_poller_ref_t poller = scheduler_io->poller; - tb_assert_and_check_return(poller); - - // loop - while (!scheduler->stopped) - { - // finish all other ready coroutines first - while (tb_co_scheduler_yield(scheduler)) - { - // spak timer - if (!tb_co_scheduler_io_timer_spak(scheduler_io)) break; - } - - // no more suspended coroutines? loop end - tb_check_break(tb_co_scheduler_suspend_count(scheduler)); - - // the delay - tb_size_t delay = tb_timer_delay(scheduler_io->timer); - - // the ldelay - tb_size_t ldelay = tb_ltimer_delay(scheduler_io->ltimer); - - // trace - tb_trace_d("loop: wait %lu ms ..", tb_min(delay, ldelay)); - - // no more ready coroutines? wait io events and timers - if (tb_poller_wait(poller, tb_co_scheduler_io_events, tb_min(delay, ldelay)) < 0) break; - - // spak timer - if (!tb_co_scheduler_io_timer_spak(scheduler_io)) break; - } -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_co_scheduler_io_ref_t tb_co_scheduler_io_init(tb_co_scheduler_t* scheduler) -{ - // done - tb_bool_t ok = tb_false; - tb_co_scheduler_io_ref_t scheduler_io = tb_null; - do - { - // init io scheduler - scheduler_io = tb_malloc0_type(tb_co_scheduler_io_t); - tb_assert_and_check_break(scheduler_io); - - // save scheduler - scheduler_io->scheduler = (tb_co_scheduler_t*)scheduler; - - // init timer and using cache time - scheduler_io->timer = tb_timer_init(TB_SCHEDULER_IO_TIMER_GROW, tb_true); - tb_assert_and_check_break(scheduler_io->timer); - - // init ltimer and using cache time - scheduler_io->ltimer = tb_ltimer_init(TB_SCHEDULER_IO_LTIMER_GROW, TB_LTIMER_TICK_S, tb_true); - tb_assert_and_check_break(scheduler_io->ltimer); - - // init poller - scheduler_io->poller = tb_poller_init(tb_null); - tb_assert_and_check_break(scheduler_io->poller); - - // start the io loop coroutine - if (!tb_co_scheduler_start(scheduler_io->scheduler, tb_co_scheduler_io_loop, scheduler_io, 0)) break; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit io scheduler - if (scheduler_io) tb_co_scheduler_io_exit(scheduler_io); - scheduler_io = tb_null; - } - - // ok? - return scheduler_io; -} -tb_void_t tb_co_scheduler_io_exit(tb_co_scheduler_io_ref_t scheduler_io) -{ - // check - tb_assert_and_check_return(scheduler_io); - - // exit poller - if (scheduler_io->poller) tb_poller_exit(scheduler_io->poller); - scheduler_io->poller = tb_null; - - // exit timer - if (scheduler_io->timer) tb_timer_exit(scheduler_io->timer); - scheduler_io->timer = tb_null; - - // exit ltimer - if (scheduler_io->ltimer) tb_ltimer_exit(scheduler_io->ltimer); - scheduler_io->ltimer = tb_null; - - // clear scheduler - scheduler_io->scheduler = tb_null; - - // exit it - tb_free(scheduler_io); -} -tb_void_t tb_co_scheduler_io_kill(tb_co_scheduler_io_ref_t scheduler_io) -{ - // check - tb_assert_and_check_return(scheduler_io); - - // trace - tb_trace_d("kill: .."); - - // kill timer - if (scheduler_io->timer) tb_timer_kill(scheduler_io->timer); - - // kill ltimer - if (scheduler_io->ltimer) tb_ltimer_kill(scheduler_io->ltimer); - - // kill poller - if (scheduler_io->poller) tb_poller_kill(scheduler_io->poller); -} -tb_pointer_t tb_co_scheduler_io_sleep(tb_co_scheduler_io_ref_t scheduler_io, tb_long_t interval) -{ - // check - tb_assert_and_check_return_val(scheduler_io && scheduler_io->poller && scheduler_io->scheduler, tb_null); - - // no sleep? - tb_check_return_val(interval, tb_null); - - // get the current coroutine - tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler); - tb_assert(coroutine); - - // trace - tb_trace_d("coroutine(%p): sleep %ld ms ..", coroutine, interval); - - // infinity? - if (interval > 0) - { - // high-precision interval? - if (interval % 1000) - { - // post task to timer - tb_timer_task_post(scheduler_io->timer, interval, tb_false, tb_co_scheduler_io_timeout, coroutine); - } - // low-precision interval? - else - { - // post task to ltimer (faster) - tb_ltimer_task_post(scheduler_io->ltimer, interval, tb_false, tb_co_scheduler_io_timeout, coroutine); - } - } - - // suspend it - return tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null); -} -tb_long_t tb_co_scheduler_io_wait(tb_co_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout) -{ - // check - tb_assert(scheduler_io && sock && scheduler_io->poller && scheduler_io->scheduler && events); - - // get the current coroutine - tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler); - tb_assert(coroutine); - - // trace - tb_trace_d("coroutine(%p): wait events(%lu) with %ld ms for socket(%p) ..", coroutine, events, timeout, sock); - - // enable edge-trigger mode if be supported - if (tb_poller_support(scheduler_io->poller, TB_POLLER_EVENT_CLEAR)) - events |= TB_POLLER_EVENT_CLEAR; - - // exists this socket? only modify events - tb_socket_ref_t sock_prev = coroutine->rs.wait.sock; - if (sock_prev == sock) - { - // return the cached events directly if the waiting events exists cache - tb_size_t events_prev = coroutine->rs.wait.events; - tb_size_t events_cache = coroutine->rs.wait.events_cache; - if (events_cache && (events_prev & events)) - { - // clear cache events - coroutine->rs.wait.events_cache &= ~events; - - // return the cached events - return events_cache & events; - } - - // modify socket from poller for waiting events if the waiting events has been changed - if (events_prev != events && !tb_poller_modify(scheduler_io->poller, sock, events, coroutine)) - { - // trace - tb_trace_e("failed to modify sock(%p) to poller on coroutine(%p)!", sock, coroutine); - - // failed - return -1; - } - } - else - { - // remove the previous socket first if exists - if (sock_prev && !tb_poller_remove(scheduler_io->poller, sock_prev)) - { - // trace - tb_trace_e("failed to remove sock(%p) to poller on coroutine(%p)!", sock_prev, coroutine); - - // failed - return -1; - } - - // insert socket to poller for waiting events - if (!tb_poller_insert(scheduler_io->poller, sock, events, coroutine)) - { - // trace - tb_trace_e("failed to insert sock(%p) to poller on coroutine(%p)!", sock, coroutine); - - // failed - return -1; - } - } - - // exists timeout? - tb_cpointer_t task = tb_null; - tb_bool_t is_ltimer = tb_false; - if (timeout >= 0) - { - // high-precision interval? - if (timeout % 1000) - { - // init task for timer - task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine); - tb_assert_and_check_return_val(task, tb_false); - } - // low-precision interval? - else - { - // init task for ltimer (faster) - task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_co_scheduler_io_timeout, coroutine); - tb_assert_and_check_return_val(task, tb_false); - - // mark as low-precision timer - is_ltimer = tb_true; - } - } - - // check - tb_assert(!((tb_size_t)(task) & 0x1)); - - // save the timer task to coroutine - coroutine->rs.wait.task = (is_ltimer || !task)? task : (tb_cpointer_t)((tb_size_t)(task) | 0x1); - - // save the socket to coroutine for the timer function - coroutine->rs.wait.sock = sock; - - // save waiting events to coroutine - coroutine->rs.wait.events = (tb_uint16_t)events; - coroutine->rs.wait.events_cache = 0; - - // mark as waiting state - coroutine->rs.wait.waiting = 1; - - // suspend the current coroutine and return the waited result - return (tb_long_t)tb_co_scheduler_suspend(scheduler_io->scheduler, tb_null); -} -tb_bool_t tb_co_scheduler_io_cancel(tb_co_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock) -{ - // check - tb_assert(scheduler_io && sock && scheduler_io->poller && scheduler_io->scheduler); - - // get the current coroutine - tb_coroutine_t* coroutine = tb_co_scheduler_running(scheduler_io->scheduler); - tb_check_return_val(coroutine, tb_false); - - // trace - tb_trace_d("coroutine(%p): cancel socket(%p) ..", coroutine, sock); - - // remove the this socket from poller - if (coroutine->rs.wait.sock == sock) - { - // remove the previous socket first if exists - if (!tb_poller_remove(scheduler_io->poller, sock)) - { - // trace - tb_trace_e("failed to remove sock(%p) to poller on coroutine(%p)!", sock, coroutine); - - // failed - return tb_false; - } - - // remove ok - return tb_true; - } - - // no this socket - return tb_false; -} -tb_co_scheduler_io_ref_t tb_co_scheduler_io_self() -{ - // get the current scheduler - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)tb_co_scheduler_self(); - - // get the current io scheduler - return scheduler? (tb_co_scheduler_io_ref_t)scheduler->scheduler_io : tb_null; -} diff --git a/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.h b/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.h deleted file mode 100644 index 5afa01ab9..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/scheduler_io.h +++ /dev/null @@ -1,125 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler_io.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_IMPL_SCHEDULER_IO_H -#define TB_COROUTINE_IMPL_SCHEDULER_IO_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "scheduler.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the io scheduler type -typedef struct __tb_co_scheduler_io_t -{ - // is stopped? - tb_bool_t stop; - - // the scheduler - tb_co_scheduler_t* scheduler; - - // the poller - tb_poller_ref_t poller; - - // the timer - tb_timer_ref_t timer; - - // the low-precision timer (faster) - tb_ltimer_ref_t ltimer; - -}tb_co_scheduler_io_t, *tb_co_scheduler_io_ref_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init io scheduler - * - * @return the io scheduler - */ -tb_co_scheduler_io_ref_t tb_co_scheduler_io_init(tb_co_scheduler_t* scheduler); - -/*! exit io scheduler - * - * @param scheduler_io the io scheduler - */ -tb_void_t tb_co_scheduler_io_exit(tb_co_scheduler_io_ref_t scheduler_io); - -/*! kill the current io scheduler - * - * @param scheduler_io the io scheduler - */ -tb_void_t tb_co_scheduler_io_kill(tb_co_scheduler_io_ref_t scheduler_io); - -/* sleep the current coroutine - * - * @param scheduler_io the io scheduler - * @param interval the interval (ms), infinity: -1 - * - * @return the user private data from resume(priv) - */ -tb_pointer_t tb_co_scheduler_io_sleep(tb_co_scheduler_io_ref_t scheduler_io, tb_long_t interval); - -/*! wait io events - * - * @param scheduler_io the io scheduler - * @param sock the socket - * @param events the waited events - * @param timeout the timeout, infinity: -1 - * - * @return > 0: the events, 0: timeout, -1: failed - */ -tb_long_t tb_co_scheduler_io_wait(tb_co_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout); - -/*! cancel io events for the given socket - * - * @param scheduler_io the io scheduler - * @param sock the socket - * - * @return tb_true or tb_false - */ -tb_bool_t tb_co_scheduler_io_cancel(tb_co_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock); - -/* get the current io scheduler - * - * @return the io scheduler - */ -tb_co_scheduler_io_ref_t tb_co_scheduler_io_self(tb_noarg_t); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/coroutine.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/coroutine.h deleted file mode 100644 index 9571b12cc..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/stackless/coroutine.h +++ /dev/null @@ -1,139 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file coroutine.h - * - */ -#ifndef TB_COROUTINE_IMPL_STACKLESS_COROUTINE_H -#define TB_COROUTINE_IMPL_STACKLESS_COROUTINE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the coroutine wait type -typedef struct __tb_lo_coroutine_rs_wait_t -{ -#ifndef TB_CONFIG_MICRO_ENABLE - /* the timer task pointer for ltimer or timer - * - * for ltimer: task - * for timer: task & 0x1 - */ - tb_cpointer_t task; -#endif - - // the socket - tb_socket_ref_t sock; - - // the waiting events - tb_sint32_t events : 6; - - // the cached events - tb_sint32_t events_cache : 6; - - // the events result (may be -1) - tb_sint32_t events_result : 6; - - // is waiting? - tb_sint32_t waiting : 1; - -}tb_lo_coroutine_rs_wait_t; - -/// the stackless coroutine type -typedef struct __tb_lo_coroutine_t -{ - // the coroutine core - tb_lo_core_t core; - - // the list entry - tb_list_entry_t entry; - - // the coroutine function - tb_lo_coroutine_func_t func; - - // the user private data of the coroutine function - tb_cpointer_t priv; - - // the user private data free function - tb_lo_coroutine_free_t free; - - // the scheduler - tb_lo_scheduler_ref_t scheduler; - - // the passed private data between resume() and suspend() - union - { - // the arguments for wait() - tb_lo_coroutine_rs_wait_t wait; - - } rs; - -}tb_lo_coroutine_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* init coroutine - * - * @param scheduler the scheduler - * @param func the coroutine function - * @param priv the passed user private data as the argument of function - * @param free the user private data free function - * - * @return the coroutine - */ -tb_lo_coroutine_t* tb_lo_coroutine_init(tb_lo_scheduler_ref_t scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free); - -/* reinit the given coroutine - * - * @param coroutine the coroutine - * @param func the coroutine function - * @param priv the passed user private data as the argument of function - * @param free the user private data free function - * - * @return tb_true or tb_false - */ -tb_bool_t tb_lo_coroutine_reinit(tb_lo_coroutine_t* coroutine, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free); - -/* exit coroutine - * - * @param coroutine the coroutine - */ -tb_void_t tb_lo_coroutine_exit(tb_lo_coroutine_t* coroutine); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/prefix.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/prefix.h deleted file mode 100644 index 032c1f1a7..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/stackless/prefix.h +++ /dev/null @@ -1,36 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_COROUTINE_IMPL_STACKLESS_PREFIX_H -#define TB_COROUTINE_IMPL_STACKLESS_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../../stackless/coroutine.h" -#include "../../../container/container.h" - - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler.h deleted file mode 100644 index 44cf5a93f..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler.h +++ /dev/null @@ -1,122 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler.h - * - */ -#ifndef TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_H -#define TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "coroutine.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// get the running coroutine -#define tb_lo_scheduler_running(scheduler) ((scheduler)->running) - -// get the ready coroutines count -#define tb_lo_scheduler_ready_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_ready) - -// get the suspended coroutines count -#define tb_lo_scheduler_suspend_count(scheduler) tb_list_entry_size(&(scheduler)->coroutines_suspend) - -// get the io scheduler -#define tb_lo_scheduler_io(scheduler) ((scheduler)->scheduler_io) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the io scheduler type -struct __tb_lo_scheduler_io_t; - -/// the stackless coroutine scheduler type -typedef struct __tb_lo_scheduler_t -{ - // is stopped - tb_bool_t stopped; - - // the running coroutine - tb_lo_coroutine_t* running; - - // the io scheduler - struct __tb_lo_scheduler_io_t* scheduler_io; - - // the dead coroutines - tb_list_entry_head_t coroutines_dead; - - /* the ready coroutines - * - * ready: head -> ready -> .. -> running -> .. -> ready -> ..-> - * | | - * ---------------------------<----------------------- - */ - tb_list_entry_head_t coroutines_ready; - - // the suspend coroutines - tb_list_entry_head_t coroutines_suspend; - -}tb_lo_scheduler_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* start coroutine - * - * @param scheduler the scheduler - * @param func the coroutine function - * @param priv the passed user private data as the argument of function - * @param free the user private data free function - * - * @return tb_true or tb_false - */ -tb_bool_t tb_lo_scheduler_start(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free); - -/* resume the given coroutine - * - * @param scheduler the scheduler - * @param coroutine the coroutine - */ -tb_void_t tb_lo_scheduler_resume(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine); - -/* get the current scheduler - * - * @return the scheduler - */ -tb_lo_scheduler_ref_t tb_lo_scheduler_self_(tb_noarg_t); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.c b/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.c deleted file mode 100644 index 5a1156a5c..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.c +++ /dev/null @@ -1,483 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler_io.c - * @ingroup coroutine - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "scheduler_io" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "scheduler_io.h" -#include "coroutine.h" -#include "../../stackless/coroutine.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the ltimer grow -#ifdef __tb_small__ -# define TB_SCHEDULER_IO_LTIMER_GROW (64) -#else -# define TB_SCHEDULER_IO_LTIMER_GROW (4096) -#endif - -// the timer grow -#define TB_SCHEDULER_IO_TIMER_GROW (TB_SCHEDULER_IO_LTIMER_GROW >> 4) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -static tb_void_t tb_lo_scheduler_io_resume(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine, tb_size_t events) -{ - // clear waiting state - coroutine->rs.wait.waiting = 0; - - // return events - coroutine->rs.wait.events_result = (tb_sint32_t)events; - - // resume the coroutine - tb_lo_scheduler_resume(scheduler, coroutine); -} -#ifndef TB_CONFIG_MICRO_ENABLE -static tb_void_t tb_lo_scheduler_io_timeout(tb_bool_t killed, tb_cpointer_t priv) -{ - // check - tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)priv; - tb_assert(coroutine); - - // get scheduler - tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler; - tb_assert(scheduler); - - // trace - tb_trace_d("coroutine(%p): timer %s", coroutine, killed? "killed" : "timeout"); - - // resume the coroutine - tb_lo_scheduler_io_resume(scheduler, coroutine, TB_POLLER_EVENT_NONE); -} -#endif -static tb_void_t tb_lo_scheduler_io_events(tb_poller_ref_t poller, tb_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv) -{ - // check - tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)priv; - tb_assert(coroutine && poller && sock && priv); - - // get scheduler - tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler; - tb_assert(scheduler); - - // trace - tb_trace_d("coroutine(%p): socket: %p, events %lu", coroutine, sock, events); - - // waiting now? - if (coroutine->rs.wait.waiting) - { - // eof for edge trigger? - if (events & TB_POLLER_EVENT_EOF) - { - // cache this eof as next recv/send event - events &= ~TB_POLLER_EVENT_EOF; - coroutine->rs.wait.events_cache |= coroutine->rs.wait.events; - } - - // resume the coroutine and pass the events to suspend() - tb_lo_scheduler_io_resume(scheduler, coroutine, events); - } - // cache this events - else coroutine->rs.wait.events_cache = events; -} -#ifndef TB_CONFIG_MICRO_ENABLE -static tb_bool_t tb_lo_scheduler_io_timer_spak(tb_lo_scheduler_io_ref_t scheduler_io) -{ - // check - tb_assert(scheduler_io && scheduler_io->timer && scheduler_io->ltimer); - - // spak ctime - tb_cache_time_spak(); - - // spak timer - if (!tb_timer_spak(scheduler_io->timer)) return tb_false; - - // spak ltimer - if (!tb_ltimer_spak(scheduler_io->ltimer)) return tb_false; - - // pk - return tb_true; -} -static tb_long_t tb_lo_scheduler_io_timer_delay(tb_lo_scheduler_io_ref_t scheduler_io) -{ - // check - tb_assert(scheduler_io && scheduler_io->timer && scheduler_io->ltimer); - - // the delay - tb_size_t delay = tb_timer_delay(scheduler_io->timer); - - // the ldelay - tb_size_t ldelay = tb_ltimer_delay(scheduler_io->ltimer); - - // return the timer delay - return tb_min(delay, ldelay); -} -#else -static __tb_inline__ tb_long_t tb_lo_scheduler_io_timer_delay(tb_lo_scheduler_io_ref_t scheduler_io) -{ - return 1000; -} -#endif -static tb_void_t tb_lo_scheduler_io_loop(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv) -{ - // check - tb_lo_scheduler_io_ref_t scheduler_io = (tb_lo_scheduler_io_ref_t)priv; - tb_assert(scheduler_io && scheduler_io->poller); - - // the scheduler - tb_lo_scheduler_t* scheduler = scheduler_io->scheduler; - tb_assert(scheduler); - - // enter coroutine - tb_lo_coroutine_enter(coroutine) - { - // loop - while (!scheduler->stopped) - { - // finish all other ready coroutines first - while (tb_lo_scheduler_ready_count(scheduler) > 1) - { - // yield it - tb_lo_coroutine_yield(); - -#ifndef TB_CONFIG_MICRO_ENABLE - // spak timer - if (!tb_lo_scheduler_io_timer_spak(scheduler_io)) break; -#endif - } - - // no more suspended coroutines? loop end - tb_check_break(tb_lo_scheduler_suspend_count(scheduler)); - - // trace - tb_trace_d("loop: wait %ld ms ..", tb_lo_scheduler_io_timer_delay(scheduler_io)); - - // no more ready coroutines? wait io events and timers (TODO) - if (tb_poller_wait(scheduler_io->poller, tb_lo_scheduler_io_events, tb_lo_scheduler_io_timer_delay(scheduler_io)) < 0) break; - -#ifndef TB_CONFIG_MICRO_ENABLE - // spak timer - if (!tb_lo_scheduler_io_timer_spak(scheduler_io)) break; -#endif - } - } -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_init(tb_lo_scheduler_t* scheduler) -{ - // done - tb_bool_t ok = tb_false; - tb_lo_scheduler_io_ref_t scheduler_io = tb_null; - do - { - // init io scheduler - scheduler_io = tb_malloc0_type(tb_lo_scheduler_io_t); - tb_assert_and_check_break(scheduler_io); - - // save scheduler - scheduler_io->scheduler = (tb_lo_scheduler_t*)scheduler; - - // init poller - scheduler_io->poller = tb_poller_init(tb_null); - tb_assert_and_check_break(scheduler_io->poller); - -#ifndef TB_CONFIG_MICRO_ENABLE - // init timer and using cache time - scheduler_io->timer = tb_timer_init(TB_SCHEDULER_IO_TIMER_GROW, tb_true); - tb_assert_and_check_break(scheduler_io->timer); - - // init ltimer and using cache time - scheduler_io->ltimer = tb_ltimer_init(TB_SCHEDULER_IO_LTIMER_GROW, TB_LTIMER_TICK_S, tb_true); - tb_assert_and_check_break(scheduler_io->ltimer); -#endif - - // start the io loop coroutine - if (!tb_lo_coroutine_start((tb_lo_scheduler_ref_t)scheduler, tb_lo_scheduler_io_loop, scheduler_io, tb_null)) break; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit io scheduler - if (scheduler_io) tb_lo_scheduler_io_exit(scheduler_io); - scheduler_io = tb_null; - } - - // ok? - return scheduler_io; -} -tb_void_t tb_lo_scheduler_io_exit(tb_lo_scheduler_io_ref_t scheduler_io) -{ - // check - tb_assert_and_check_return(scheduler_io); - - // exit poller - if (scheduler_io->poller) tb_poller_exit(scheduler_io->poller); - scheduler_io->poller = tb_null; - -#ifndef TB_CONFIG_MICRO_ENABLE - // exit timer - if (scheduler_io->timer) tb_timer_exit(scheduler_io->timer); - scheduler_io->timer = tb_null; - - // exit ltimer - if (scheduler_io->ltimer) tb_ltimer_exit(scheduler_io->ltimer); - scheduler_io->ltimer = tb_null; -#endif - - // clear scheduler - scheduler_io->scheduler = tb_null; - - // exit it - tb_free(scheduler_io); -} -tb_void_t tb_lo_scheduler_io_kill(tb_lo_scheduler_io_ref_t scheduler_io) -{ - // check - tb_assert_and_check_return(scheduler_io); - - // trace - tb_trace_d("kill: .."); - -#ifndef TB_CONFIG_MICRO_ENABLE - // kill timer - if (scheduler_io->timer) tb_timer_kill(scheduler_io->timer); - - // kill ltimer - if (scheduler_io->ltimer) tb_ltimer_kill(scheduler_io->ltimer); -#endif - - // kill poller - if (scheduler_io->poller) tb_poller_kill(scheduler_io->poller); -} -tb_void_t tb_lo_scheduler_io_sleep(tb_lo_scheduler_io_ref_t scheduler_io, tb_long_t interval) -{ -#ifndef TB_CONFIG_MICRO_ENABLE - // check - tb_assert_and_check_return(scheduler_io && scheduler_io->poller && scheduler_io->scheduler); - - // get the current coroutine - tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler); - tb_assert(coroutine); - - // trace - tb_trace_d("coroutine(%p): sleep %ld ms ..", coroutine, interval); - - // infinity? - if (interval > 0) - { - // high-precision interval? - if (interval % 1000) - { - // post task to timer - tb_timer_task_post(scheduler_io->timer, interval, tb_false, tb_lo_scheduler_io_timeout, coroutine); - } - // low-precision interval? - else - { - // post task to ltimer (faster) - tb_ltimer_task_post(scheduler_io->ltimer, interval, tb_false, tb_lo_scheduler_io_timeout, coroutine); - } - } -#else - // not impl - tb_trace_noimpl(); -#endif -} -tb_bool_t tb_lo_scheduler_io_wait(tb_lo_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout) -{ - // check - tb_assert(scheduler_io && sock && scheduler_io->poller && scheduler_io->scheduler && events); - - // get the current coroutine - tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler); - tb_assert(coroutine); - - // trace - tb_trace_d("coroutine(%p): wait events(%lu) with %ld ms for socket(%p) ..", coroutine, events, timeout, sock); - - // enable edge-trigger mode if be supported - if (tb_poller_support(scheduler_io->poller, TB_POLLER_EVENT_CLEAR)) - events |= TB_POLLER_EVENT_CLEAR; - - // exists this socket? only modify events - tb_socket_ref_t sock_prev = coroutine->rs.wait.sock; - if (sock_prev == sock) - { - // return the cached events directly if the waiting events exists cache - tb_size_t events_prev = coroutine->rs.wait.events; - tb_size_t events_cache = coroutine->rs.wait.events_cache; - if (events_cache && (events_prev & events)) - { - // clear cache events - coroutine->rs.wait.events_cache &= ~events; - - // return the cached events - coroutine->rs.wait.events_result = events_cache & events; - return tb_false; - } - - // modify socket from poller for waiting events if the waiting events has been changed - if (events_prev != events && !tb_poller_modify(scheduler_io->poller, sock, events, coroutine)) - { - // trace - tb_trace_e("failed to modify sock(%p) to poller on coroutine(%p)!", sock, coroutine); - - // failed - coroutine->rs.wait.events_result = -1; - return tb_false; - } - } - else - { - // remove the previous socket first if exists - if (sock_prev && !tb_poller_remove(scheduler_io->poller, sock_prev)) - { - // trace - tb_trace_e("failed to remove sock(%p) to poller on coroutine(%p)!", sock_prev, coroutine); - - // failed - coroutine->rs.wait.events_result = -1; - return tb_false; - } - - // insert socket to poller for waiting events - if (!tb_poller_insert(scheduler_io->poller, sock, events, coroutine)) - { - // trace - tb_trace_e("failed to insert sock(%p) to poller on coroutine(%p)!", sock, coroutine); - - // failed - coroutine->rs.wait.events_result = -1; - return tb_false; - } - } - -#ifndef TB_CONFIG_MICRO_ENABLE - // exists timeout? - tb_cpointer_t task = tb_null; - tb_bool_t is_ltimer = tb_false; - if (timeout >= 0) - { - // high-precision interval? - if (timeout % 1000) - { - // init task for timer - task = tb_timer_task_init(scheduler_io->timer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine); - tb_assert_and_check_return_val(task, tb_false); - } - // low-precision interval? - else - { - // init task for ltimer (faster) - task = tb_ltimer_task_init(scheduler_io->ltimer, timeout, tb_false, tb_lo_scheduler_io_timeout, coroutine); - tb_assert_and_check_return_val(task, tb_false); - - // mark as low-precision timer - is_ltimer = tb_true; - } - } - - // check - tb_assert(!((tb_size_t)(task) & 0x1)); - - // save the timer task to coroutine - coroutine->rs.wait.task = (is_ltimer || !task)? task : (tb_cpointer_t)((tb_size_t)(task) | 0x1); -#endif - - // save the socket to coroutine for the timer function - coroutine->rs.wait.sock = sock; - - // save waiting events to coroutine - coroutine->rs.wait.events = (tb_sint32_t)events; - coroutine->rs.wait.events_cache = 0; - coroutine->rs.wait.events_result = 0; - - // mark as waiting state - coroutine->rs.wait.waiting = 1; - - // suspend it - return tb_true; -} -tb_bool_t tb_lo_scheduler_io_cancel(tb_lo_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock) -{ - // check - tb_assert(scheduler_io && sock && scheduler_io->poller && scheduler_io->scheduler); - - // get the current coroutine - tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler); - tb_check_return_val(coroutine, tb_false); - - // trace - tb_trace_d("coroutine(%p): cancel socket(%p) ..", coroutine, sock); - - // remove the this socket from poller - if (coroutine->rs.wait.sock == sock) - { - // remove the previous socket first if exists - if (!tb_poller_remove(scheduler_io->poller, sock)) - { - // trace - tb_trace_e("failed to remove sock(%p) to poller on coroutine(%p)!", sock, coroutine); - - // failed - coroutine->rs.wait.events_result = -1; - return tb_false; - } - - // remove ok - coroutine->rs.wait.events_result = 0; - return tb_true; - } - - // no this socket - return tb_false; -} -tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_self() -{ - // get the current scheduler - tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)tb_lo_scheduler_self_(); - - // get the current io scheduler - return scheduler? (tb_lo_scheduler_io_ref_t)scheduler->scheduler_io : tb_null; -} diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.h deleted file mode 100644 index f73481260..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/stackless/scheduler_io.h +++ /dev/null @@ -1,125 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler_io.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_IO_H -#define TB_COROUTINE_IMPL_STACKLESS_SCHEDULER_IO_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "scheduler.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the io scheduler type -typedef struct __tb_lo_scheduler_io_t -{ - // is stopped? - tb_bool_t stop; - - // the scheduler - tb_lo_scheduler_t* scheduler; - - // the poller - tb_poller_ref_t poller; - -#ifndef TB_CONFIG_MICRO_ENABLE - // the timer - tb_timer_ref_t timer; - - // the low-precision timer (faster) - tb_ltimer_ref_t ltimer; -#endif - -}tb_lo_scheduler_io_t, *tb_lo_scheduler_io_ref_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* init io scheduler - * - * @return the io scheduler - */ -tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_init(tb_lo_scheduler_t* scheduler); - -/* exit io scheduler - * - * @param scheduler_io the io scheduler - */ -tb_void_t tb_lo_scheduler_io_exit(tb_lo_scheduler_io_ref_t scheduler_io); - -/* kill the current io scheduler - * - * @param scheduler_io the io scheduler - */ -tb_void_t tb_lo_scheduler_io_kill(tb_lo_scheduler_io_ref_t scheduler_io); - -/* sleep the current coroutine - * - * @param scheduler_io the io scheduler - * @param interval the interval (ms), infinity: -1 - */ -tb_void_t tb_lo_scheduler_io_sleep(tb_lo_scheduler_io_ref_t scheduler_io, tb_long_t interval); - -/* wait io events - * - * @param scheduler_io the io scheduler - * @param sock the socket - * @param events the waited events - * @param timeout the timeout, infinity: -1 - * - * @return suspend coroutine if be tb_true - */ -tb_bool_t tb_lo_scheduler_io_wait(tb_lo_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout); - -/*! cancel io events for the given socket - * - * @param scheduler_io the io scheduler - * @param sock the socket - * - * return tb_true or tb_false - */ -tb_bool_t tb_lo_scheduler_io_cancel(tb_lo_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock); - -/* get the current io scheduler - * - * @return the io scheduler - */ -tb_lo_scheduler_io_ref_t tb_lo_scheduler_io_self(tb_noarg_t); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/impl/stackless/stackless.h b/core/src/tbox/src/tbox/coroutine/impl/stackless/stackless.h deleted file mode 100644 index 18dd9aa4d..000000000 --- a/core/src/tbox/src/tbox/coroutine/impl/stackless/stackless.h +++ /dev/null @@ -1,35 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file coroutine.h - * - */ -#ifndef TB_COROUTINE_IMPL_STACKLESS_H -#define TB_COROUTINE_IMPL_STACKLESS_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "coroutine.h" -#include "scheduler.h" -#include "scheduler_io.h" - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/lock.c b/core/src/tbox/src/tbox/coroutine/lock.c deleted file mode 100644 index 9e40927d7..000000000 --- a/core/src/tbox/src/tbox/coroutine/lock.c +++ /dev/null @@ -1,66 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file lock.h - * @ingroup coroutine - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "lock" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "lock.h" -#include "semaphore.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_co_lock_ref_t tb_co_lock_init() -{ - // init lock - return (tb_co_lock_ref_t)tb_co_semaphore_init(1); -} -tb_void_t tb_co_lock_exit(tb_co_lock_ref_t self) -{ - // exit lock - tb_co_semaphore_exit((tb_co_semaphore_ref_t)self); -} -tb_void_t tb_co_lock_enter(tb_co_lock_ref_t self) -{ - // enter lock - tb_co_semaphore_wait((tb_co_semaphore_ref_t)self, -1); -} -tb_bool_t tb_co_lock_enter_try(tb_co_lock_ref_t self) -{ - // try to enter lock - return tb_co_semaphore_wait((tb_co_semaphore_ref_t)self, 0) > 0; -} -tb_void_t tb_co_lock_leave(tb_co_lock_ref_t self) -{ - // leave lock - tb_co_semaphore_post((tb_co_semaphore_ref_t)self, 1); -} diff --git a/core/src/tbox/src/tbox/coroutine/lock.h b/core/src/tbox/src/tbox/coroutine/lock.h deleted file mode 100644 index 1c3ab2473..000000000 --- a/core/src/tbox/src/tbox/coroutine/lock.h +++ /dev/null @@ -1,87 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file lock.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_LOCK_H -#define TB_COROUTINE_LOCK_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the coroutine lock ref type -typedef __tb_typeref__(co_lock); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init lock - * - * @return the lock - */ -tb_co_lock_ref_t tb_co_lock_init(tb_noarg_t); - -/*! exit lock - * - * @param lock the lock - */ -tb_void_t tb_co_lock_exit(tb_co_lock_ref_t lock); - -/*! enter lock - * - * @param lock the lock - */ -tb_void_t tb_co_lock_enter(tb_co_lock_ref_t lock); - -/*! try to enter lock - * - * @param lock the lock - * - * @return tb_true or tb_false - */ -tb_bool_t tb_co_lock_enter_try(tb_co_lock_ref_t lock); - -/*! leave lock - * - * @param lock the lock - */ -tb_void_t tb_co_lock_leave(tb_co_lock_ref_t lock); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/prefix.h b/core/src/tbox/src/tbox/coroutine/prefix.h deleted file mode 100644 index a937c67c0..000000000 --- a/core/src/tbox/src/tbox/coroutine/prefix.h +++ /dev/null @@ -1,34 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_COROUTINE_PREFIX_H -#define TB_COROUTINE_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" - - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/scheduler.c b/core/src/tbox/src/tbox/coroutine/scheduler.c deleted file mode 100644 index bbe9016cd..000000000 --- a/core/src/tbox/src/tbox/coroutine/scheduler.c +++ /dev/null @@ -1,220 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler.h - * @ingroup scheduler - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "scheduler" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "scheduler.h" -#include "impl/impl.h" -#include "../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * globals - */ - -// the self scheduler local -static tb_thread_local_t s_scheduler_self = TB_THREAD_LOCAL_INIT; - -// the global scheduler for the exclusive mode -static tb_co_scheduler_t* s_scheduler_self_ex = tb_null; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -static tb_void_t tb_co_scheduler_free(tb_list_entry_head_ref_t coroutines) -{ - // check - tb_assert(coroutines); - - // free all coroutines - while (tb_list_entry_size(coroutines)) - { - // get the next entry from head - tb_list_entry_ref_t entry = tb_list_entry_head(coroutines); - tb_assert(entry); - - // remove it from the ready coroutines - tb_list_entry_remove_head(coroutines); - - // exit this coroutine - tb_coroutine_exit((tb_coroutine_t*)tb_list_entry0(entry)); - } -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_co_scheduler_ref_t tb_co_scheduler_init() -{ - // done - tb_bool_t ok = tb_false; - tb_co_scheduler_t* scheduler = tb_null; - do - { - // make scheduler - scheduler = tb_malloc0_type(tb_co_scheduler_t); - tb_assert_and_check_break(scheduler); - - // init dead coroutines - tb_list_entry_init(&scheduler->coroutines_dead, tb_coroutine_t, entry, tb_null); - - // init ready coroutines - tb_list_entry_init(&scheduler->coroutines_ready, tb_coroutine_t, entry, tb_null); - - // init suspend coroutines - tb_list_entry_init(&scheduler->coroutines_suspend, tb_coroutine_t, entry, tb_null); - - // init original coroutine - scheduler->original.scheduler = (tb_co_scheduler_ref_t)scheduler; - - // init running - scheduler->running = &scheduler->original; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (scheduler) tb_co_scheduler_exit((tb_co_scheduler_ref_t)scheduler); - scheduler = tb_null; - } - - // ok? - return (tb_co_scheduler_ref_t)scheduler; -} -tb_void_t tb_co_scheduler_exit(tb_co_scheduler_ref_t self) -{ - // check - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)self; - tb_assert_and_check_return(scheduler); - - // must be stopped - tb_assert(scheduler->stopped); - - // exit io scheduler first - if (scheduler->scheduler_io) tb_co_scheduler_io_exit(scheduler->scheduler_io); - scheduler->scheduler_io = tb_null; - - // clear running - scheduler->running = tb_null; - - // check coroutines - tb_assert(!tb_list_entry_size(&scheduler->coroutines_ready)); - tb_assert(!tb_list_entry_size(&scheduler->coroutines_suspend)); - - // free all dead coroutines - tb_co_scheduler_free(&scheduler->coroutines_dead); - - // free all ready coroutines - tb_co_scheduler_free(&scheduler->coroutines_ready); - - // free all suspend coroutines - tb_co_scheduler_free(&scheduler->coroutines_suspend); - - // exit dead coroutines - tb_list_entry_exit(&scheduler->coroutines_dead); - - // exit ready coroutines - tb_list_entry_exit(&scheduler->coroutines_ready); - - // exit suspend coroutines - tb_list_entry_exit(&scheduler->coroutines_suspend); - - // exit the scheduler - tb_free(scheduler); -} -tb_void_t tb_co_scheduler_kill(tb_co_scheduler_ref_t self) -{ - // check - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)self; - tb_assert_and_check_return(scheduler); - - // stop it - scheduler->stopped = tb_true; - - // kill the io scheduler - if (scheduler->scheduler_io) tb_co_scheduler_io_kill(scheduler->scheduler_io); -} -tb_void_t tb_co_scheduler_loop(tb_co_scheduler_ref_t self, tb_bool_t exclusive) -{ - // check - tb_co_scheduler_t* scheduler = (tb_co_scheduler_t*)self; - tb_assert_and_check_return(scheduler); - - // is exclusive mode? - if (exclusive) s_scheduler_self_ex = scheduler; - else - { - // init self scheduler local - if (!tb_thread_local_init(&s_scheduler_self, tb_null)) return ; - - // update and overide the current scheduler - tb_thread_local_set(&s_scheduler_self, self); - } - - // schedule all ready coroutines - while (tb_list_entry_size(&scheduler->coroutines_ready)) - { - // check - tb_assert(tb_coroutine_is_original(scheduler->running)); - - // get the next entry from head - tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_ready); - tb_assert(entry); - - // switch to the next coroutine - tb_co_scheduler_switch(scheduler, (tb_coroutine_t*)tb_list_entry0(entry)); - - // trace - tb_trace_d("[loop]: ready %lu", tb_list_entry_size(&scheduler->coroutines_ready)); - } - - // stop it - scheduler->stopped = tb_true; - - // is exclusive mode? - if (exclusive) s_scheduler_self_ex = tb_null; - else - { - // clear the current scheduler - tb_thread_local_set(&s_scheduler_self, tb_null); - } -} -tb_co_scheduler_ref_t tb_co_scheduler_self() -{ - // get self scheduler on the current thread - return (tb_co_scheduler_ref_t)(s_scheduler_self_ex? s_scheduler_self_ex : tb_thread_local_get(&s_scheduler_self)); -} diff --git a/core/src/tbox/src/tbox/coroutine/scheduler.h b/core/src/tbox/src/tbox/coroutine/scheduler.h deleted file mode 100644 index 78ebdcb8c..000000000 --- a/core/src/tbox/src/tbox/coroutine/scheduler.h +++ /dev/null @@ -1,87 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_SCHEDULER_H -#define TB_COROUTINE_SCHEDULER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the coroutine scheduler ref type -typedef __tb_typeref__(co_scheduler); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init scheduler - * - * @return the scheduler - */ -tb_co_scheduler_ref_t tb_co_scheduler_init(tb_noarg_t); - -/*! exit scheduler - * - * @param scheduler the scheduler - */ -tb_void_t tb_co_scheduler_exit(tb_co_scheduler_ref_t scheduler); - -/* kill the scheduler - * - * @param scheduler the scheduler - */ -tb_void_t tb_co_scheduler_kill(tb_co_scheduler_ref_t scheduler); - -/*! run the scheduler loop - * - * @param scheduler the scheduler - * @param exclusive enable exclusive mode, we need ensure only one loop() be called at the same time, - * but it will be faster using thr global scheduler instead of TLS storage - */ -tb_void_t tb_co_scheduler_loop(tb_co_scheduler_ref_t schedule, tb_bool_t exclusive); - -/*! get the scheduler of the current coroutine - * - * @return the scheduler - */ -tb_co_scheduler_ref_t tb_co_scheduler_self(tb_noarg_t); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/semaphore.c b/core/src/tbox/src/tbox/coroutine/semaphore.c deleted file mode 100644 index be1335012..000000000 --- a/core/src/tbox/src/tbox/coroutine/semaphore.c +++ /dev/null @@ -1,176 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file semaphore.h - * @ingroup coroutine - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "semaphore" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "semaphore.h" -#include "coroutine.h" -#include "scheduler.h" -#include "impl/impl.h" -#include "../container/container.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the coroutine semaphore type -typedef struct __tb_co_semaphore_t -{ - // the semaphore value - tb_size_t value; - - // the waiting coroutines - tb_single_list_entry_head_t waiting; - -}tb_co_semaphore_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_co_semaphore_ref_t tb_co_semaphore_init(tb_size_t value) -{ - // done - tb_bool_t ok = tb_false; - tb_co_semaphore_t* semaphore = tb_null; - do - { - // make semaphore - semaphore = tb_malloc0_type(tb_co_semaphore_t); - tb_assert_and_check_break(semaphore); - - // init value - semaphore->value = value; - - // init waiting coroutines - tb_single_list_entry_init(&semaphore->waiting, tb_coroutine_t, rs.single_entry, tb_null); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (semaphore) tb_co_semaphore_exit((tb_co_semaphore_ref_t)semaphore); - semaphore = tb_null; - } - - // ok? - return (tb_co_semaphore_ref_t)semaphore; -} -tb_void_t tb_co_semaphore_exit(tb_co_semaphore_ref_t self) -{ - // check - tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self; - tb_assert_and_check_return(semaphore); - - // check waiting coroutines - tb_assert(!tb_single_list_entry_size(&semaphore->waiting)); - - // exit waiting coroutines - tb_single_list_entry_exit(&semaphore->waiting); - - // exit the semaphore - tb_free(semaphore); -} -tb_void_t tb_co_semaphore_post(tb_co_semaphore_ref_t self, tb_size_t post) -{ - // check - tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self; - tb_assert_and_check_return(semaphore); - - // add the semaphore value - tb_size_t value = semaphore->value + post; - - // resume the waiting coroutines - while (value && tb_single_list_entry_size(&semaphore->waiting)) - { - // get the next entry from head - tb_single_list_entry_ref_t entry = tb_single_list_entry_head(&semaphore->waiting); - tb_assert_and_check_break(entry); - - // remove it from the waiting coroutines - tb_single_list_entry_remove_head(&semaphore->waiting); - - // get the waiting coroutine - tb_coroutine_ref_t coroutine = (tb_coroutine_ref_t)tb_single_list_entry(&semaphore->waiting, entry); - - // resume this coroutine - tb_coroutine_resume(coroutine, (tb_cpointer_t)tb_true); - - // decrease the semaphore value - value--; - } - - // update the semaphore value - semaphore->value = value; -} -tb_size_t tb_co_semaphore_value(tb_co_semaphore_ref_t self) -{ - // check - tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self; - tb_assert_and_check_return_val(semaphore, 0); - - // get the semaphore value - return semaphore->value; -} -tb_long_t tb_co_semaphore_wait(tb_co_semaphore_ref_t self, tb_long_t timeout) -{ - // check - tb_co_semaphore_t* semaphore = (tb_co_semaphore_t*)self; - tb_assert_and_check_return_val(semaphore, -1); - - // attempt to get the semaphore value - tb_long_t ok = 1; - if (semaphore->value) semaphore->value--; - // no semaphore? - else if (timeout) - { - // get the running coroutine - tb_coroutine_t* running = (tb_coroutine_t*)tb_coroutine_self(); - tb_assert(running); - - // save this coroutine to the waiting coroutines - tb_single_list_entry_insert_tail(&semaphore->waiting, &running->rs.single_entry); - - // wait semaphore - ok = (tb_long_t)tb_coroutine_sleep(timeout); - } - // timeout and no waiting - else ok = 0; - - // ok? - return ok; -} diff --git a/core/src/tbox/src/tbox/coroutine/semaphore.h b/core/src/tbox/src/tbox/coroutine/semaphore.h deleted file mode 100644 index a9eede0ac..000000000 --- a/core/src/tbox/src/tbox/coroutine/semaphore.h +++ /dev/null @@ -1,95 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file semaphore.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_SEMAPHORE_H -#define TB_COROUTINE_SEMAPHORE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the coroutine semaphore ref type -typedef __tb_typeref__(co_semaphore); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init semaphore - * - * @param value the initial semaphore value - * - * @return the semaphore - */ -tb_co_semaphore_ref_t tb_co_semaphore_init(tb_size_t value); - -/*! exit semaphore - * - * @return the semaphore - */ -tb_void_t tb_co_semaphore_exit(tb_co_semaphore_ref_t semaphore); - -/*! post semaphore - * - * @param semaphore the semaphore - * @param post the post semaphore value - * - * @return tb_true or tb_false - */ -tb_void_t tb_co_semaphore_post(tb_co_semaphore_ref_t semaphore, tb_size_t post); - -/*! the semaphore value - * - * @param semaphore the semaphore - * - * @return the semaphore value - */ -tb_size_t tb_co_semaphore_value(tb_co_semaphore_ref_t semaphore); - -/*! wait semaphore - * - * @param semaphore the semaphore - * @param timeout the timeout - * - * @return ok: 1, timeout: 0, fail: -1 - */ -tb_long_t tb_co_semaphore_wait(tb_co_semaphore_ref_t semaphore, tb_long_t timeout); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/stackless/core.h b/core/src/tbox/src/tbox/coroutine/stackless/core.h deleted file mode 100644 index 1322ed11a..000000000 --- a/core/src/tbox/src/tbox/coroutine/stackless/core.h +++ /dev/null @@ -1,171 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file core.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_STACKLESS_CORE_H -#define TB_COROUTINE_STACKLESS_CORE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -/* - * Copyright (c) 2004-2005, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -// get core from coroutine -#define tb_lo_core(co) ((tb_lo_core_ref_t)(co)) - -// get core state -#define tb_lo_core_state(co) (tb_lo_core(co)->state) - -// set core state -#define tb_lo_core_state_set(co, val) tb_lo_core(co)->state = (val) - -#ifdef TB_COMPILER_IS_GCC -/* - * Implementation of local continuations based on the "Labels as - * values" feature of gcc - * - * @author Adam Dunkels <[email protected]> - * - * This implementation of local continuations is based on a special - * feature of the GCC C compiler called "labels as values". This - * feature allows assigning pointers with the address of the code - * corresponding to a particular C label. - * - * For more information, see the GCC documentation: - * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html - */ -# define tb_lo_core_init(co) tb_lo_core(co)->branch = tb_null; tb_lo_core(co)->state = TB_STATE_READY -# define tb_lo_core_resume(co) \ - if (tb_lo_core(co)->branch) \ - { \ - goto *(tb_lo_core(co)->branch); \ - } \ - else - -# define tb_lo_core_record(co) \ - do \ - { \ - __tb_mconcat_ex__(__tb_lo_core_label, __tb_line__): \ - tb_lo_core(co)->branch = &&__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__); \ - \ - } while(0) - -# define tb_lo_core_exit(co) tb_lo_core(co)->branch = tb_null, tb_lo_core(co)->state = TB_STATE_END - -#else - -/* - * Implementation of local continuations based on switch() statment - * - * @author Adam Dunkels <[email protected]> - * - * This implementation of local continuations uses the C switch() - * statement to resume execution of a function somewhere inside the - * function's body. The implementation is based on the fact that - * switch() statements are able to jump directly into the bodies of - * control structures such as if() or while() statmenets. - * - * This implementation borrows heavily from Simon Tatham's coroutines - * implementation in C: - * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html - * - * - * - * WARNING! the implementation using switch() does not work if an - * core_set() is done within another switch() statement! - */ -# define tb_lo_core_init(co) tb_lo_core(co)->branch = 0; tb_lo_core(co)->state = TB_STATE_READY -# define tb_lo_core_resume(co) switch (tb_lo_core(co)->branch) case 0: -# define tb_lo_core_record_(co, label) tb_lo_core(co)->branch = (tb_uint16_t)label; case label: -# define tb_lo_core_exit(co) tb_lo_core(co)->branch = 0, tb_lo_core(co)->state = TB_STATE_END -# ifdef TB_COMPILER_IS_MSVC -# define tb_lo_core_record(co) tb_lo_core_record_(co, __COUNTER__ + 1) -# else -# define tb_lo_core_record(co) tb_lo_core_record_(co, __tb_line__) -# endif -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the core branch type -#ifdef TB_COMPILER_IS_GCC -typedef tb_pointer_t tb_lo_core_branch_t; -#else -typedef tb_uint16_t tb_lo_core_branch_t; -#endif - -// the stackless coroutine core type -typedef struct __tb_lo_core_t -{ - // the code branch - tb_lo_core_branch_t branch; - - /* the state - * - * TB_STATE_READY - * TB_STATE_SUSPEND - * TB_STATE_END - */ - tb_uint8_t state; - -}tb_lo_core_t, *tb_lo_core_ref_t; - - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/stackless/coroutine.c b/core/src/tbox/src/tbox/coroutine/stackless/coroutine.c deleted file mode 100644 index c04769d2a..000000000 --- a/core/src/tbox/src/tbox/coroutine/stackless/coroutine.c +++ /dev/null @@ -1,197 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file coroutine.h - * @ingroup coroutine - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "coroutine" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "coroutine.h" -#include "scheduler.h" -#include "../impl/impl.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -tb_lo_coroutine_t* tb_lo_coroutine_init(tb_lo_scheduler_ref_t scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free) -{ - // check - tb_assert_and_check_return_val(scheduler && func, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_lo_coroutine_t* coroutine = tb_null; - do - { - // make coroutine - coroutine = tb_malloc0_type(tb_lo_coroutine_t); - tb_assert_and_check_break(coroutine); - - // init core - tb_lo_core_init(&coroutine->core); - - // save scheduler - coroutine->scheduler = scheduler; - - // init function and user private data - coroutine->func = func; - coroutine->priv = priv; - coroutine->free = free; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (coroutine) tb_lo_coroutine_exit(coroutine); - coroutine = tb_null; - } - - // trace - tb_trace_d("init %p", coroutine); - - // ok? - return coroutine; -} -tb_bool_t tb_lo_coroutine_reinit(tb_lo_coroutine_t* coroutine, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free) -{ - // check - tb_assert_and_check_return_val(coroutine && func, tb_false); - tb_assert_and_check_return_val(coroutine->scheduler && tb_lo_core_state(coroutine) == TB_STATE_END, tb_false); - - // init core - tb_lo_core_init(&coroutine->core); - - // init function and user private data - coroutine->func = func; - coroutine->priv = priv; - coroutine->free = free; - - // init rs data - tb_memset(&coroutine->rs, 0, sizeof(coroutine->rs)); - - // ok - return tb_true; -} -tb_void_t tb_lo_coroutine_exit(tb_lo_coroutine_t* coroutine) -{ - // check - tb_assert_and_check_return(coroutine && tb_lo_core_state(coroutine) == TB_STATE_END); - - // trace - tb_trace_d("exit: %p", coroutine); - - // exit it - tb_free(coroutine); -} -tb_lo_scheduler_ref_t tb_lo_coroutine_scheduler_(tb_lo_coroutine_ref_t self) -{ - // check - tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self; - tb_assert(coroutine); - - // get scheduler - return coroutine->scheduler; -} -tb_void_t tb_lo_coroutine_sleep_(tb_lo_coroutine_ref_t self, tb_long_t interval) -{ - // check - tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self; - tb_assert(coroutine); - - // get scheduler - tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler; - tb_assert(scheduler); - - // init io scheduler first - if (!scheduler->scheduler_io) scheduler->scheduler_io = tb_lo_scheduler_io_init(scheduler); - tb_assert(scheduler->scheduler_io); - - // sleep it - tb_lo_scheduler_io_sleep(scheduler->scheduler_io, interval); -} -tb_bool_t tb_lo_coroutine_waitio_(tb_lo_coroutine_ref_t self, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout) -{ - // check - tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self; - tb_assert(coroutine); - - // get scheduler - tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)coroutine->scheduler; - tb_assert(scheduler); - - // init io scheduler first - if (!scheduler->scheduler_io) scheduler->scheduler_io = tb_lo_scheduler_io_init(scheduler); - tb_assert(scheduler->scheduler_io); - - // wait it - return tb_lo_scheduler_io_wait(scheduler->scheduler_io, sock, events, timeout); -} -tb_long_t tb_lo_coroutine_events_(tb_lo_coroutine_ref_t self) -{ - // check - tb_lo_coroutine_t* coroutine = (tb_lo_coroutine_t*)self; - tb_assert(coroutine); - - // get events - return coroutine->rs.wait.events_result; -} -tb_void_t tb_lo_coroutine_pass_free_(tb_cpointer_t priv) -{ - if (priv) tb_free(priv); -} -tb_pointer_t tb_lo_coroutine_pass1_make_(tb_size_t type_size, tb_cpointer_t value, tb_size_t offset, tb_size_t size) -{ - // check - tb_assert(type_size && value && offset + size <= type_size); - - // make data - tb_byte_t* data = tb_malloc0_bytes(type_size); - if (data) tb_memcpy(data + offset, value, size); - - // ok? - return data; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * public implementation - */ -tb_bool_t tb_lo_coroutine_start(tb_lo_scheduler_ref_t self, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free) -{ - return tb_lo_scheduler_start((tb_lo_scheduler_t*)self, func, priv, free); -} -tb_void_t tb_lo_coroutine_resume(tb_lo_coroutine_ref_t self) -{ - tb_lo_scheduler_resume((tb_lo_scheduler_t*)tb_lo_coroutine_scheduler_(self), (tb_lo_coroutine_t*)self); -} diff --git a/core/src/tbox/src/tbox/coroutine/stackless/coroutine.h b/core/src/tbox/src/tbox/coroutine/stackless/coroutine.h deleted file mode 100644 index cc71cb96d..000000000 --- a/core/src/tbox/src/tbox/coroutine/stackless/coroutine.h +++ /dev/null @@ -1,413 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file coroutine.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_STACKLESS_COROUTINE_H -#define TB_COROUTINE_STACKLESS_COROUTINE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "core.h" -#include "scheduler.h" -#include "../../libc/libc.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -/// the self coroutine -#define tb_lo_coroutine_self() (co__) - -/* enter coroutine - * - * @code - * - // before - tb_lo_coroutine_enter(co) - { - for (i = 0; i < 100; i++) - { - tb_lo_coroutine_yield(); - } - } - - // after expanding again (init: branch = 0, state = TB_STATE_READY) - tb_lo_coroutine_ref_t co__ = co; - tb_int_t lo_yield_flag__ = 1; - for (; lo_yield_flag__; tb_lo_core(co__)->branch = 0, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0) - switch (tb_lo_core(co__)->branch) - case 0: - { - for (i = 0; i < 100; i++) - { - lo_yield_flag__ = 0; - tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:; - if (lo_yield_flag__ == 0) - return ; - } - } - - // or .. - - // after expanding again for gcc label (init: branch = tb_null, state = TB_STATE_READY) - tb_lo_coroutine_ref_t co__ = co; - tb_int_t lo_yield_flag__ = 1; - for (; lo_yield_flag__; tb_lo_core(co__)->branch = tb_null, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0) - if (tb_lo_core(co)->branch) - { - goto *(tb_lo_core(co)->branch); - } - else - { - for (i = 0; i < 100; i++) - { - lo_yield_flag__ = 0; - do - { - __tb_mconcat_ex__(__tb_lo_core_label, __tb_line__): - tb_lo_core(co)->branch = &&__tb_mconcat_ex__(__tb_lo_core_label, __tb_line__); - - } while(0) - - if (lo_yield_flag__ == 0) - return ; - } - } - - * @endcode - */ -#define tb_lo_coroutine_enter(co) \ - tb_lo_coroutine_ref_t co__ = (co); \ - tb_int_t lo_yield_flag__ = 1; \ - for ( ; lo_yield_flag__; tb_lo_core_exit(tb_lo_coroutine_self()), lo_yield_flag__ = 0) \ - tb_lo_core_resume(tb_lo_coroutine_self()) - -/// yield coroutine -#define tb_lo_coroutine_yield() \ -do \ -{ \ - lo_yield_flag__ = 0; \ - tb_lo_core_record(co__); \ - if (lo_yield_flag__ == 0) \ - return ; \ - \ -} while(0) - -/*! suspend current coroutine - * - * the scheduler will move this coroutine to the suspended coroutines after the function be returned - * - * @code - * - // before - tb_lo_coroutine_enter(co) - { - for (i = 0; i < 100; i++) - { - tb_lo_coroutine_yield(); - tb_lo_coroutine_suspend(); - } - } - - // after expanding again (init: branch = 0, state = TB_STATE_READY) - tb_lo_coroutine_ref_t co__ = co; - tb_int_t lo_yield_flag__ = 1; - for (; lo_yield_flag__; tb_lo_core(co__)->branch = 0, tb_lo_core(co__)->state = TB_STATE_END, lo_yield_flag__ = 0) - switch (tb_lo_core(co__)->branch) - case 0: - { - for (i = 0; i < 100; i++) - { - lo_yield_flag__ = 0; - tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:; - if (lo_yield_flag__ == 0) - return ; - - // suspend coroutine - tb_lo_core(co__)->state = TB_STATE_SUSPEND; - tb_lo_core(co__)->branch = __tb_line__; case __tb_line__:; - if (tb_lo_core(co__)->state == TB_STATE_SUSPEND) - return ; - } - } - * @endcode - */ -#define tb_lo_coroutine_suspend() \ -do \ -{ \ - tb_used(&lo_yield_flag__); \ - tb_lo_core_state_set(tb_lo_coroutine_self(), TB_STATE_SUSPEND); \ - tb_lo_core_record(tb_lo_coroutine_self()); \ - if (tb_lo_core_state(tb_lo_coroutine_self()) == TB_STATE_SUSPEND) \ - return ; \ - \ -} while(0) - -/// sleep some time -#define tb_lo_coroutine_sleep(interval) \ -do \ -{ \ - if (interval) \ - { \ - tb_lo_coroutine_sleep_(tb_lo_coroutine_self(), interval); \ - tb_lo_coroutine_suspend(); \ - } \ - \ -} while(0) - -/// wait io socket events -#define tb_lo_coroutine_waitio(sock, events, interval) \ -do \ -{ \ - if (tb_lo_coroutine_waitio_(tb_lo_coroutine_self(), sock, events, interval)) \ - { \ - tb_lo_coroutine_suspend(); \ - } \ - \ -} while(0) - -/// wait until coroutine be true -#define tb_lo_coroutine_wait_until(cond) \ -do \ -{ \ - tb_used(&lo_yield_flag__); \ - tb_lo_core_record(tb_lo_coroutine_self()); \ - if (!(cond)) \ - return ; \ - \ -} while(0) - -/// wait while coroutine be true -#define tb_lo_coroutine_wait_while(pt, cond) tb_lo_coroutine_wait_until(!(cond)) - -/// get socket events after waiting -#define tb_lo_coroutine_events() tb_lo_coroutine_events_(tb_lo_coroutine_self()) - -/*! pass the user private data - * - * @code - - // start coroutine - tb_lo_coroutine_start(scheduler, coroutine_func, tb_lo_coroutine_pass(tb_xxxx_priv_t)); - - * @endcode - * - * => - * - * @code - - // start coroutine - tb_lo_coroutine_start(scheduler, coroutine_func, tb_malloc0_type(tb_xxxx_priv_t), tb_lo_coroutine_pass_free_); - - * @endcode - */ -#define tb_lo_coroutine_pass(type) tb_malloc0_type(type), tb_lo_coroutine_pass_free_ - -/*! pass the user private data and init one member - * - * @code - - typedef struct __tb_xxxx_priv_t - { - tb_size_t member; - tb_size_t others; - - }tb_xxxx_priv_t; - - // start coroutine - tb_lo_coroutine_start(scheduler, coroutine_func, tb_lo_coroutine_pass1(tb_xxxx_priv_t, member, value)); - - * @endcode - * - * => - * - * @code - - tb_xxxx_priv_t* priv = tb_malloc0_type(tb_xxxx_priv_t); - if (priv) - { - priv->member = value; - } - - // start coroutine - tb_lo_coroutine_start(scheduler, coroutine_func, priv, tb_lo_coroutine_pass_free_); - - * @endcode - */ -#define tb_lo_coroutine_pass1(type, member, value) tb_lo_coroutine_pass1_make_(sizeof(type), &(value), tb_offsetof(type, member), tb_memsizeof(type, member)), tb_lo_coroutine_pass_free_ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private interfaces - */ - -/* get the scheduler of coroutine - * - * @param coroutine the coroutine - * - * @return the scheduler - */ -tb_lo_scheduler_ref_t tb_lo_coroutine_scheduler_(tb_lo_coroutine_ref_t coroutine); - -/* sleep the current coroutine - * - * @param coroutine the coroutine - * @param interval the interval (ms), infinity: -1 - */ -tb_void_t tb_lo_coroutine_sleep_(tb_lo_coroutine_ref_t coroutine, tb_long_t interval); - -/* wait io events - * - * @param coroutine the coroutine - * @param sock the socket - * @param events the waited events - * @param timeout the timeout, infinity: -1 - * - * @return suspend coroutine if be tb_true - */ -tb_bool_t tb_lo_coroutine_waitio_(tb_lo_coroutine_ref_t coroutine, tb_socket_ref_t sock, tb_size_t events, tb_long_t timeout); - -/* get the events after waiting socket - * - * @param coroutine the coroutine - * - * @return events: > 0, failed: -1, timeout: 0 - */ -tb_long_t tb_lo_coroutine_events_(tb_lo_coroutine_ref_t coroutine); - -/* free the user private data for pass() - * - * @note only be a wrapper of free() for tb_lo_coroutine_pass() - * - * @param priv the user private data - */ -tb_void_t tb_lo_coroutine_pass_free_(tb_cpointer_t priv); - -/* make the user private data for pass1() - * - * @param type_size the data type size - * @param value the value pointer - * @param offset the member offset - * @param size the value size - * - * @return the user private data - */ -tb_pointer_t tb_lo_coroutine_pass1_make_(tb_size_t type_size, tb_cpointer_t value, tb_size_t offset, tb_size_t size); - -/* make the user private data for pass2() - * - * @param type_size the data type size - * @param value1 the value1 pointer - * @param offset1 the member1 offset - * @param size1 the value1 size - * @param value2 the value2 pointer - * @param offset2 the member2 offset - * @param size2 the value2 size - * - * @return the user private data - */ -tb_pointer_t tb_lo_coroutine_pass2_make_(tb_size_t type_size, tb_cpointer_t value1, tb_size_t offset1, tb_size_t size1, tb_cpointer_t value2, tb_size_t offset2, tb_size_t size2); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! start coroutine - * - * @code - static tb_void_t switchtask(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv) - { - // get count pointer (@note only allow non-status local variables) - tb_size_t* count = (tb_size_t*)priv; - - // enter coroutine - tb_lo_coroutine_enter(coroutine); - - // @note can not define local variables here - // ... - - // loop - while ((*count)--) - { - // yield - tb_lo_coroutine_yield(); - } - - // leave coroutine - tb_lo_coroutine_leave(); - } - - tb_int_t main (tb_int_t argc, tb_char_t** argv) - { - // init tbox - if (!tb_init(tb_null, tb_null)) return -1; - - // init scheduler - tb_lo_scheduler_ref_t scheduler = tb_lo_scheduler_init(); - if (scheduler) - { - // start coroutine - tb_size_t counts[] = {100, 100}; - tb_lo_coroutine_start(scheduler, switchtask, &counts[0], tb_null); - tb_lo_coroutine_start(scheduler, switchtask, &counts[1], tb_null); - - // run scheduler - tb_lo_scheduler_loop(scheduler); - - // exit scheduler - tb_lo_scheduler_exit(scheduler); - } - - // exit tbox - tb_exit(); - } - - * @endcode - * - * @param scheduler the scheduler (can not be null, we can get scheduler of the current coroutine from tb_lo_scheduler_self()) - * @param func the coroutine function - * @param priv the passed user private data as the argument of function - * @param free the user private free function - * - * @return tb_true or tb_false - */ -tb_bool_t tb_lo_coroutine_start(tb_lo_scheduler_ref_t scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free); - -/*! resume the given coroutine - * - * @param coroutine the coroutine - */ -tb_void_t tb_lo_coroutine_resume(tb_lo_coroutine_ref_t coroutine); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/stackless/lock.h b/core/src/tbox/src/tbox/coroutine/stackless/lock.h deleted file mode 100644 index a5b82f3f7..000000000 --- a/core/src/tbox/src/tbox/coroutine/stackless/lock.h +++ /dev/null @@ -1,81 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file lock.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_STACKLESS_LOCK_H -#define TB_COROUTINE_STACKLESS_LOCK_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "semaphore.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -/*! init lock - * - * @param lock the lock pointer - */ -#define tb_lo_lock_init(lock) tb_lo_semaphore_init(lock, 1) - -/*! exit lock - * - * @param lock the lock pointer - */ -#define tb_lo_lock_exit(lock) tb_lo_semaphore_exit(lock) - -/*! enter lock - * - * @param lock the lock pointer - */ -#define tb_lo_lock_enter(lock) tb_lo_semaphore_wait(lock) - -/*! try to enter lock - * - * @param lock the lock pointer - * - * @return tb_true or tb_false - */ -#define tb_lo_lock_enter_try(lock) tb_lo_semaphore_wait_try(lock) - -/*! leave lock - * - * @param lock the lock pointer - */ -#define tb_lo_lock_leave(lock) tb_lo_semaphore_post(lock, 1) - - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the stackless lock type -typedef tb_lo_semaphore_t tb_lo_lock_t; - -/// the stackless lock ref type -typedef tb_lo_semaphore_ref_t tb_lo_lock_ref_t; - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/stackless/prefix.h b/core/src/tbox/src/tbox/coroutine/stackless/prefix.h deleted file mode 100644 index 1abfd678f..000000000 --- a/core/src/tbox/src/tbox/coroutine/stackless/prefix.h +++ /dev/null @@ -1,57 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_COROUTINE_STACKLESS_PREFIX_H -#define TB_COROUTINE_STACKLESS_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the stackless coroutine ref type -typedef __tb_typeref__(lo_coroutine); - -/// the stackless scheduler ref type -typedef __tb_typeref__(lo_scheduler); - -/*! the coroutine function type - * - * @param coroutine the coroutine self - * @param priv the user private data from start(.., priv) - */ -typedef tb_void_t (*tb_lo_coroutine_func_t)(tb_lo_coroutine_ref_t coroutine, tb_cpointer_t priv); - -/*! the user private data free function type - * - * @param priv the user private data from start(.., priv) - */ -typedef tb_void_t (*tb_lo_coroutine_free_t)(tb_cpointer_t priv); - - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/stackless/scheduler.c b/core/src/tbox/src/tbox/coroutine/stackless/scheduler.c deleted file mode 100644 index 3f996e7f2..000000000 --- a/core/src/tbox/src/tbox/coroutine/stackless/scheduler.c +++ /dev/null @@ -1,414 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler.h - * @ingroup scheduler - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "scheduler" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "scheduler.h" -#include "../impl/impl.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the dead cache maximum count -#if defined(TB_CONFIG_MICRO_ENABLE) -# define TB_SCHEDULER_DEAD_CACHE_MAXN (8) -#elif defined(__tb_small__) -# define TB_SCHEDULER_DEAD_CACHE_MAXN (64) -#else -# define TB_SCHEDULER_DEAD_CACHE_MAXN (256) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * globals - */ - -#ifndef TB_CONFIG_MICRO_ENABLE -// the self scheduler local -static tb_thread_local_t s_scheduler_self = TB_THREAD_LOCAL_INIT; -#endif - -// the global scheduler for the exclusive mode -static tb_lo_scheduler_t* s_scheduler_self_ex = tb_null; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -static tb_void_t tb_lo_scheduler_free(tb_list_entry_head_ref_t coroutines) -{ - // check - tb_assert(coroutines); - - // free all coroutines - while (tb_list_entry_size(coroutines)) - { - // get the next entry from head - tb_list_entry_ref_t entry = tb_list_entry_head(coroutines); - tb_assert(entry); - - // remove it from the ready coroutines - tb_list_entry_remove_head(coroutines); - - // exit this coroutine - tb_lo_coroutine_exit((tb_lo_coroutine_t*)tb_list_entry(coroutines, entry)); - } -} -static tb_void_t tb_lo_scheduler_make_ready(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine) -{ - // check - tb_assert(scheduler && coroutine); - - // mark ready state - tb_lo_core_state_set(coroutine, TB_STATE_READY); - - // insert this coroutine to ready coroutines - if (scheduler->running) - { - // .. -> coroutine(inserted) -> running -> .. - tb_list_entry_insert_prev(&scheduler->coroutines_ready, &scheduler->running->entry, &coroutine->entry); - } - else - { - // .. last -> coroutine(inserted) - tb_list_entry_insert_tail(&scheduler->coroutines_ready, &coroutine->entry); - } -} -static tb_void_t tb_lo_scheduler_make_dead(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine) -{ - // check - tb_assert(scheduler && coroutine); - tb_assert(tb_lo_core_state(coroutine) == TB_STATE_END); - - // trace - tb_trace_d("finish coroutine(%p)", coroutine); - - // free the user private data first - if (coroutine->free) coroutine->free(coroutine->priv); - - // remove this coroutine from the ready coroutines - tb_list_entry_remove(&scheduler->coroutines_ready, &coroutine->entry); - - // append this coroutine to dead coroutines - tb_list_entry_insert_tail(&scheduler->coroutines_dead, &coroutine->entry); -} -static tb_void_t tb_lo_scheduler_make_suspend(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine) -{ - // check - tb_assert(scheduler && coroutine); - tb_assert(tb_lo_core_state(coroutine) == TB_STATE_SUSPEND); - - // trace - tb_trace_d("suspend coroutine(%p)", coroutine); - - // remove this coroutine from the ready coroutines - tb_list_entry_remove(&scheduler->coroutines_ready, &coroutine->entry); - - // append this coroutine to suspend coroutines - tb_list_entry_insert_tail(&scheduler->coroutines_suspend, &coroutine->entry); -} -static __tb_inline__ tb_lo_coroutine_t* tb_lo_scheduler_next_ready(tb_lo_scheduler_t* scheduler) -{ - // check - tb_assert(scheduler && tb_list_entry_size(&scheduler->coroutines_ready)); - - // get the next entry - tb_list_entry_ref_t entry_next = scheduler->running? tb_list_entry_next(&scheduler->running->entry) : tb_list_entry_head(&scheduler->coroutines_ready); - tb_assert(entry_next); - - // is list header? skip it and get the first entry - if (entry_next == (tb_list_entry_ref_t)&scheduler->coroutines_ready) - entry_next = tb_list_entry_next(entry_next); - - // get the next ready coroutine - return (tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_ready, entry_next); -} -static tb_void_t tb_lo_scheduler_switch(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine) -{ - // check - tb_assert(scheduler && coroutine && coroutine->func); - tb_assert(tb_lo_core_state(coroutine) == TB_STATE_READY); - - // trace - tb_trace_d("switch to coroutine(%p) from coroutine(%p)", coroutine, scheduler->running); - - // mark the given coroutine as running - scheduler->running = coroutine; - - // call the coroutine function - coroutine->func((tb_lo_coroutine_ref_t)coroutine, coroutine->priv); -} -tb_bool_t tb_lo_scheduler_start(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free) -{ - // check - tb_assert(func); - - // done - tb_bool_t ok = tb_false; - tb_lo_coroutine_t* coroutine = tb_null; - do - { - // trace - tb_trace_d("start .."); - - // get the current scheduler - if (!scheduler) scheduler = (tb_lo_scheduler_t*)tb_lo_scheduler_self_(); - tb_assert_and_check_break(scheduler); - - // have been stopped? do not continue to start new coroutines - tb_check_break(!scheduler->stopped); - - // reuses dead coroutines in init function - if (tb_list_entry_size(&scheduler->coroutines_dead)) - { - // get the next entry from head - tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead); - tb_assert_and_check_break(entry); - - // remove it from the ready coroutines - tb_list_entry_remove_head(&scheduler->coroutines_dead); - - // get the dead coroutine - coroutine = (tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_dead, entry); - - // reinit this coroutine - tb_lo_coroutine_reinit(coroutine, func, priv, free); - } - - // init coroutine - if (!coroutine) coroutine = tb_lo_coroutine_init((tb_lo_scheduler_ref_t)scheduler, func, priv, free); - tb_assert_and_check_break(coroutine); - - // ready coroutine - tb_lo_scheduler_make_ready(scheduler, coroutine); - - // the dead coroutines is too much? free some coroutines - while (tb_list_entry_size(&scheduler->coroutines_dead) > TB_SCHEDULER_DEAD_CACHE_MAXN) - { - // get the next entry from head - tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead); - tb_assert(entry); - - // remove it from the ready coroutines - tb_list_entry_remove_head(&scheduler->coroutines_dead); - - // exit this coroutine - tb_lo_coroutine_exit((tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_dead, entry)); - } - - // ok - ok = tb_true; - - } while (0); - - // trace - tb_trace_d("start %s", ok? "ok" : "no"); - - // ok? - return ok; -} -tb_void_t tb_lo_scheduler_resume(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine) -{ - // check - tb_assert(scheduler && coroutine); - tb_assert(tb_lo_core_state(coroutine) == TB_STATE_SUSPEND); - - // remove it from the suspend coroutines - tb_list_entry_remove(&scheduler->coroutines_suspend, &coroutine->entry); - - // make it as ready - tb_lo_scheduler_make_ready(scheduler, coroutine); -} -tb_lo_scheduler_ref_t tb_lo_scheduler_self_() -{ -#ifndef TB_CONFIG_MICRO_ENABLE - // get self scheduler on the current thread - return (tb_lo_scheduler_ref_t)(s_scheduler_self_ex? s_scheduler_self_ex : tb_thread_local_get(&s_scheduler_self)); -#else - return (tb_lo_scheduler_ref_t)s_scheduler_self_ex; -#endif -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * public implementation - */ -tb_lo_scheduler_ref_t tb_lo_scheduler_init() -{ - // done - tb_bool_t ok = tb_false; - tb_lo_scheduler_t* scheduler = tb_null; - do - { - // make scheduler - scheduler = tb_malloc0_type(tb_lo_scheduler_t); - tb_assert_and_check_break(scheduler); - - // init dead coroutines - tb_list_entry_init(&scheduler->coroutines_dead, tb_lo_coroutine_t, entry, tb_null); - - // init ready coroutines - tb_list_entry_init(&scheduler->coroutines_ready, tb_lo_coroutine_t, entry, tb_null); - - // init suspend coroutines - tb_list_entry_init(&scheduler->coroutines_suspend, tb_lo_coroutine_t, entry, tb_null); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (scheduler) tb_lo_scheduler_exit((tb_lo_scheduler_ref_t)scheduler); - scheduler = tb_null; - } - - // ok? - return (tb_lo_scheduler_ref_t)scheduler; -} -tb_void_t tb_lo_scheduler_exit(tb_lo_scheduler_ref_t self) -{ - // check - tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)self; - tb_assert_and_check_return(scheduler); - - // must be stopped - tb_assert(scheduler->stopped); - - // exit io scheduler first - if (scheduler->scheduler_io) tb_lo_scheduler_io_exit(scheduler->scheduler_io); - scheduler->scheduler_io = tb_null; - - // check coroutines - tb_assert(!tb_list_entry_size(&scheduler->coroutines_ready)); - tb_assert(!tb_list_entry_size(&scheduler->coroutines_suspend)); - - // free all dead coroutines - tb_lo_scheduler_free(&scheduler->coroutines_dead); - - // free all ready coroutines - tb_lo_scheduler_free(&scheduler->coroutines_ready); - - // free all suspend coroutines - tb_lo_scheduler_free(&scheduler->coroutines_suspend); - - // exit dead coroutines - tb_list_entry_exit(&scheduler->coroutines_dead); - - // exit ready coroutines - tb_list_entry_exit(&scheduler->coroutines_ready); - - // exit suspend coroutines - tb_list_entry_exit(&scheduler->coroutines_suspend); - - // exit the scheduler - tb_free(scheduler); -} -tb_void_t tb_lo_scheduler_kill(tb_lo_scheduler_ref_t self) -{ - // check - tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)self; - tb_assert_and_check_return(scheduler); - - // stop it - scheduler->stopped = tb_true; -} -tb_void_t tb_lo_scheduler_loop(tb_lo_scheduler_ref_t self, tb_bool_t exclusive) -{ - // check - tb_lo_scheduler_t* scheduler = (tb_lo_scheduler_t*)self; - tb_assert_and_check_return(scheduler); - - // is exclusive mode? - if (exclusive) s_scheduler_self_ex = scheduler; -#ifndef TB_CONFIG_MICRO_ENABLE - else - { - // init self scheduler local - if (!tb_thread_local_init(&s_scheduler_self, tb_null)) return ; - - // update and overide the current scheduler - tb_thread_local_set(&s_scheduler_self, self); - } -#else - else - { - // trace - tb_trace_e("non-exclusive is not suspported in micro mode!"); - } -#endif - - // schedule all ready coroutines - while (tb_list_entry_size(&scheduler->coroutines_ready) && !scheduler->stopped) - { - // trace - tb_trace_d("[loop]: ready %lu", tb_list_entry_size(&scheduler->coroutines_ready)); - - // get the next ready coroutine - tb_lo_coroutine_t* coroutine_next = tb_lo_scheduler_next_ready(scheduler); - tb_assert(coroutine_next); - - // process the running coroutine - if (scheduler->running) - { - // get the state of running coroutine - tb_size_t state = tb_lo_core_state(scheduler->running); - - // mark this coroutine as dead if the running coroutine(root level) have been finished - if (state == TB_STATE_END) - tb_lo_scheduler_make_dead(scheduler, scheduler->running); - // suspend the running coroutine - else if (state == TB_STATE_SUSPEND) - tb_lo_scheduler_make_suspend(scheduler, scheduler->running); - } - - // switch to it if the next coroutine (may be running coroutine) is ready - if (tb_lo_core_state(coroutine_next) == TB_STATE_READY) - tb_lo_scheduler_switch(scheduler, coroutine_next); - } - - // stop it - scheduler->stopped = tb_true; - - // is exclusive mode? - if (exclusive) s_scheduler_self_ex = tb_null; -#ifndef TB_CONFIG_MICRO_ENABLE - else - { - // clear the current scheduler - tb_thread_local_set(&s_scheduler_self, tb_null); - } -#endif -} - diff --git a/core/src/tbox/src/tbox/coroutine/stackless/scheduler.h b/core/src/tbox/src/tbox/coroutine/stackless/scheduler.h deleted file mode 100644 index a3d19c15d..000000000 --- a/core/src/tbox/src/tbox/coroutine/stackless/scheduler.h +++ /dev/null @@ -1,81 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file scheduler.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_STACKLESS_SCHEDULER_H -#define TB_COROUTINE_STACKLESS_SCHEDULER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -/// the self scheduler -#define tb_lo_scheduler_self() tb_lo_coroutine_scheduler_(co__) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init scheduler - * - * @return the scheduler - */ -tb_lo_scheduler_ref_t tb_lo_scheduler_init(tb_noarg_t); - -/*! exit scheduler - * - * @param scheduler the scheduler - */ -tb_void_t tb_lo_scheduler_exit(tb_lo_scheduler_ref_t scheduler); - -/* kill the scheduler - * - * @param scheduler the scheduler - */ -tb_void_t tb_lo_scheduler_kill(tb_lo_scheduler_ref_t scheduler); - -/*! run the scheduler loop - * - * @param scheduler the scheduler - * @param exclusive enable exclusive mode, we need ensure only one loop() be called at the same time, - * but it will be faster using thr global scheduler instead of TLS storage - */ -tb_void_t tb_lo_scheduler_loop(tb_lo_scheduler_ref_t scheduler, tb_bool_t exclusive); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/stackless/semaphore.h b/core/src/tbox/src/tbox/coroutine/stackless/semaphore.h deleted file mode 100644 index 495883b1b..000000000 --- a/core/src/tbox/src/tbox/coroutine/stackless/semaphore.h +++ /dev/null @@ -1,104 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file semaphore.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_STACKLESS_SEMAPHORE_H -#define TB_COROUTINE_STACKLESS_SEMAPHORE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "coroutine.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -/*! init semaphore - * - * @param sem the semaphore pointer - * @param val the initial semaphore value - */ -#define tb_lo_semaphore_init(sem, val) (sem)->value = val - -/*! exit semaphore - * - * @param sem the semaphore pointer - */ -#define tb_lo_semaphore_exit(sem) (sem)->value = 0 - -/*! get semaphore value - * - * @param sem the semaphore pointer - * - * @return the semaphore value - */ -#define tb_lo_semaphore_value(sem) ((sem)->value) - -/*! post semaphore - * - * @param sem the semaphore pointer - * @param post the post semaphore value - */ -#define tb_lo_semaphore_post(sem, post) \ -do \ -{ \ - (sem)->value += (post); \ - tb_lo_coroutine_yield(); \ - \ -} while (0) - -/*! wait semaphore - * - * @param sem the semaphore pointer - */ -#define tb_lo_semaphore_wait(sem) \ -do \ -{ \ - tb_lo_coroutine_wait_until((sem)->value > 0); \ - (sem)->value--; \ - \ -} while(0) - -/*! try to wait semaphore - * - * @param sem the semaphore pointer - * - * @return tb_true or tb_false - */ -#define tb_lo_semaphore_wait_try(sem) (((sem)->value > 0)? (sem)->value-- : 0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the stackless semaphore type -typedef struct __tb_lo_semaphore_t -{ - // the semaphore value - tb_long_t value; - -}tb_lo_semaphore_t, *tb_lo_semaphore_ref_t; - -#endif diff --git a/core/src/tbox/src/tbox/coroutine/stackless/stackless.h b/core/src/tbox/src/tbox/coroutine/stackless/stackless.h deleted file mode 100644 index 9b0b5d916..000000000 --- a/core/src/tbox/src/tbox/coroutine/stackless/stackless.h +++ /dev/null @@ -1,38 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file stackless.h - * @ingroup coroutine - * - */ -#ifndef TB_COROUTINE_STACKLESS_H -#define TB_COROUTINE_STACKLESS_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "coroutine.h" -#include "scheduler.h" -#include "semaphore.h" -#include "lock.h" - - -#endif diff --git a/core/src/tbox/src/tbox/database/database.h b/core/src/tbox/src/tbox/database/database.h deleted file mode 100644 index 1546e107b..000000000 --- a/core/src/tbox/src/tbox/database/database.h +++ /dev/null @@ -1,36 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file database.h - * @defgroup database - */ -#ifndef TB_DATABASE_H -#define TB_DATABASE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "sql.h" - - - -#endif diff --git a/core/src/tbox/src/tbox/database/impl/mysql.c b/core/src/tbox/src/tbox/database/impl/mysql.c deleted file mode 100644 index e0e4e5e19..000000000 --- a/core/src/tbox/src/tbox/database/impl/mysql.c +++ /dev/null @@ -1,1705 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file mysql.c - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "mysql" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include <mysql.h> -#include <errmsg.h> -#include <mysqld_error.h> - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the mysql result row type -typedef struct __tb_database_mysql_result_row_t -{ - // the iterator - tb_iterator_t itor; - - // the row - MYSQL_ROW row; - - // the lengths - tb_ulong_t* lengths; - - // the col count - tb_size_t count; - - // the col value - tb_database_sql_value_t value; - -}tb_database_mysql_result_row_t; - -// the mysql result type -typedef struct __tb_database_mysql_result_t -{ - // the iterator - tb_iterator_t itor; - - // the statement - MYSQL_STMT* statement; - - // the result - MYSQL_RES* result; - - // the fields - MYSQL_FIELD* fields; - - // the metadata - MYSQL_RES* metadata; - - // the row count - tb_size_t count; - - // try loading all? - tb_bool_t try_all; - - // the row - tb_database_mysql_result_row_t row; - - // the stream - tb_stream_ref_t stream; - -}tb_database_mysql_result_t; - -// the mysql stream type -typedef struct __tb_database_mysql_stream_impl_t -{ - // the statement - MYSQL_STMT* statement; - - // the result - MYSQL_BIND* result; - - // the offset - tb_size_t offset; - - // the column - tb_size_t column; - -}tb_database_mysql_stream_impl_t; - -// the mysql type -typedef struct __tb_database_mysql_t -{ - // the base - tb_database_sql_impl_t base; - - // the result - tb_database_mysql_result_t result; - - // the database - MYSQL* database; - - // the bind list - MYSQL_BIND* bind_list; - - // the bind maxn - tb_size_t bind_maxn; - - // the bind data - tb_buffer_t bind_data; - -}tb_database_mysql_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * declaration - */ -static tb_void_t tb_database_mysql_result_exit(tb_database_sql_impl_t* database, tb_iterator_ref_t result); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * library implementation - */ -static tb_handle_t tb_database_mysql_library_init(tb_cpointer_t* ppriv) -{ - // init it - if (mysql_library_init(0, tb_null, tb_null)) - { - // trace - tb_trace_e("init: mysql library failed!"); - return tb_null; - } - - // ok - return ppriv; -} -static tb_void_t tb_database_mysql_library_exit(tb_handle_t handle, tb_cpointer_t priv) -{ - // exit it - mysql_library_end(); -} -static tb_handle_t tb_database_mysql_library_load() -{ - return tb_singleton_instance(TB_SINGLETON_TYPE_LIBRARY_MYSQL, tb_database_mysql_library_init, tb_database_mysql_library_exit, tb_null, tb_null); -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * state implementation - */ -static tb_size_t tb_database_mysql_state_from_errno(tb_size_t errno) -{ - // done - tb_size_t state = TB_STATE_DATABASE_UNKNOWN_ERROR; - switch (errno) - { - case ER_NO_DB_ERROR: - case ER_BAD_DB_ERROR: - state = TB_STATE_DATABASE_NO_SUCH_DATABASE; - break; - case ER_NO_SUCH_TABLE: - state = TB_STATE_DATABASE_NO_SUCH_TABLE; - break; - case ER_BAD_FIELD_ERROR: - state = TB_STATE_DATABASE_NO_SUCH_FIELD; - break; - case ER_ACCESS_DENIED_ERROR: - state = TB_STATE_DATABASE_ACCESS_DENIED; - break; - case ER_PARSE_ERROR: - state = TB_STATE_DATABASE_PARSE_ERROR; - break; - case ER_WRONG_VALUE_COUNT_ON_ROW: - state = TB_STATE_DATABASE_VALUE_COUNT_ERROR; - break; - case CR_UNKNOWN_HOST: - state = TB_STATE_DATABASE_UNKNOWN_HOST; - break; - case ER_UNKNOWN_ERROR: - break; - default: - tb_trace_e("unknown errno: %lu", errno); - break; - } - - // ok? - return state; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * stream implementation - */ -static tb_bool_t tb_database_mysql_stream_impl_open(tb_stream_ref_t stream) -{ - // check - tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream; - tb_assert_and_check_return_val(impl && impl->statement, tb_false); - - // check result - tb_assert_and_check_return_val(impl->result && impl->result->buffer && impl->result->buffer_length, tb_false); - - // ok - return tb_true; -} -static tb_bool_t tb_database_mysql_stream_impl_clos(tb_stream_ref_t stream) -{ - // check - tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream; - tb_assert_and_check_return_val(impl, tb_false); - - // ok - return tb_true; -} -static tb_long_t tb_database_mysql_stream_impl_read(tb_stream_ref_t stream, tb_byte_t* data, tb_size_t size) -{ - // check - tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream; - tb_assert_and_check_return_val(impl && impl->statement, -1); - - // check data and size - tb_check_return_val(data, -1); - tb_check_return_val(size, 0); - - // check result - tb_assert_and_check_return_val(impl->result && impl->result->buffer && impl->result->buffer_length, -1); - - // the length - tb_size_t length = (tb_size_t)*impl->result->length; - - // end? - tb_check_return_val(length && impl->offset < length, -1); - - // read data - size = tb_min3(size, (tb_size_t)impl->result->buffer_length, length - impl->offset); - if (size) tb_memcpy(data, impl->result->buffer, size); - - // update offset - impl->offset += size; - - // fetch column - if (mysql_stmt_fetch_column(impl->statement, impl->result, impl->column, impl->offset)) - { - // trace - tb_trace_e("stream: fetch failed at: %lu, error[%d]: %s", impl->column, mysql_stmt_errno(impl->statement), mysql_stmt_error(impl->statement)); - return -1; - } - - // trace -// tb_trace_d("stream: read: %lu", size); - - // ok? - return (tb_long_t)(size); -} -static tb_long_t tb_database_mysql_stream_impl_wait(tb_stream_ref_t stream, tb_size_t wait, tb_long_t timeout) -{ - // check - tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream; - tb_assert_and_check_return_val(impl, -1); - - // ok? - return wait; -} -static tb_bool_t tb_database_mysql_stream_impl_ctrl(tb_stream_ref_t stream, tb_size_t ctrl, tb_va_list_t args) -{ - // check - tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream; - tb_assert_and_check_return_val(impl, tb_false); - - // ctrl - switch (ctrl) - { - case TB_STREAM_CTRL_GET_SIZE: - { - // the psize - tb_hong_t* psize = (tb_hong_t*)tb_va_arg(args, tb_hong_t*); - tb_assert_and_check_return_val(psize && impl->result, tb_false); - - // get size - *psize = (tb_hong_t)*impl->result->length; - - // ok - return tb_true; - } - default: - break; - } - return tb_false; -} -static tb_stream_ref_t tb_database_mysql_stream_impl_init(MYSQL_STMT* statement, MYSQL_BIND* result, tb_size_t column) -{ - // check - tb_assert_and_check_return_val(statement && result, tb_null); - - // init stream - tb_stream_ref_t stream = tb_stream_init( TB_STREAM_TYPE_NONE - , sizeof(tb_database_mysql_stream_impl_t) - , 0 - , tb_database_mysql_stream_impl_open - , tb_database_mysql_stream_impl_clos - , tb_null - , tb_database_mysql_stream_impl_ctrl - , tb_database_mysql_stream_impl_wait - , tb_database_mysql_stream_impl_read - , tb_null - , tb_null - , tb_null - , tb_null); - tb_assert_and_check_return_val(stream, tb_null); - - // init the stream impl - tb_database_mysql_stream_impl_t* impl = (tb_database_mysql_stream_impl_t*)stream; - if (impl) - { - impl->statement = statement; - impl->result = result; - impl->column = column; - } - - // ok? - return (tb_stream_ref_t)stream; -} -static tb_bool_t tb_database_mysql_stream_impl_set_value(tb_database_sql_value_t* value, tb_database_mysql_t* mysql, MYSQL_BIND* result, tb_size_t column) -{ - // check - tb_assert_and_check_return_val(value && mysql && mysql->result.statement && result, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // exit the last stream first - if (mysql->result.stream) tb_stream_exit(mysql->result.stream); - mysql->result.stream = tb_null; - - // init stream - mysql->result.stream = tb_database_mysql_stream_impl_init(mysql->result.statement, result, column); - tb_assert_and_check_break(mysql->result.stream); - - // open stream - if (!tb_stream_open(mysql->result.stream)) break; - - // set blob32 - tb_database_sql_value_set_blob32(value, tb_null, 0, mysql->result.stream); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (mysql->result.stream) tb_stream_exit(mysql->result.stream); - mysql->result.stream = tb_null; - } - - // ok? - return ok; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * iterator implementation - */ -static tb_size_t tb_database_mysql_result_row_iterator_size(tb_iterator_ref_t iterator) -{ - // check - tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator; - tb_assert(result); - - // size - return result->count; -} -static tb_size_t tb_database_mysql_result_row_iterator_head(tb_iterator_ref_t iterator) -{ - // head - return 0; -} -static tb_size_t tb_database_mysql_result_row_iterator_tail(tb_iterator_ref_t iterator) -{ - // check - tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator; - tb_assert(result); - - // tail - return result->count; -} -static tb_size_t tb_database_mysql_result_row_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator; - tb_assert(result); - tb_assert_and_check_return_val(itor && itor <= result->count, result->count); - - // load all? - tb_assert_and_check_return_val(result->try_all, result->count); - - // prev - return itor - 1; -} -static tb_size_t tb_database_mysql_result_row_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator; - tb_assert(result); - tb_assert_and_check_return_val(itor < result->count, result->count); - - // not load all? try fetching it - if (!result->try_all) - { - // fetch statement - if (result->statement) - { - // fetch the row - tb_int_t ok = 0; - if ((ok = mysql_stmt_fetch(result->statement))) - { - // end or error? - if (ok != MYSQL_DATA_TRUNCATED) - { - // error? - if (ok != MYSQL_NO_DATA) - { - // the mysql - tb_database_mysql_t* mysql = (tb_database_mysql_t*)iterator->priv; - - // save state - if (mysql) mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(result->statement)); - - // trace - tb_trace_e("statement: fetch row %lu failed, error[%d]: %s", itor, mysql_stmt_errno(result->statement), mysql_stmt_error(result->statement)); - } - - // end - return result->count; - } - } - } - // fetch result - else - { - // check - tb_assert_and_check_return_val(result->result, result->count); - - // fetch the row - result->row.row = mysql_fetch_row(result->result); - tb_check_return_val(result->row.row, result->count); - - // fetch the lengths - result->row.lengths = mysql_fetch_lengths(result->result); - tb_assert_and_check_return_val(result->row.lengths, result->count); - } - } - - // next - return itor + 1; -} -static tb_pointer_t tb_database_mysql_result_row_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_mysql_result_t* result = (tb_database_mysql_result_t*)iterator; - tb_assert_and_check_return_val(result && itor < result->count, tb_null); - - // load all? - if (result->try_all) - { - // load statement row - if (result->statement) - { - // seek to the row number - mysql_stmt_data_seek(result->statement, itor); - - // fetch the row - tb_int_t ok = 0; - if ((ok = mysql_stmt_fetch(result->statement))) - { - // end or error? - if (ok != MYSQL_DATA_TRUNCATED) - { - // error? - if (ok != MYSQL_NO_DATA) - { - // the mysql - tb_database_mysql_t* mysql = (tb_database_mysql_t*)iterator->priv; - - // save state - if (mysql) mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(result->statement)); - - // trace - tb_trace_e("statement: fetch row %lu failed, error[%d]: %s", itor, mysql_stmt_errno(result->statement), mysql_stmt_error(result->statement)); - } - return tb_null; - } - } - } - // load result row - else - { - // check - tb_assert_and_check_return_val(result->result, tb_null); - - // seek to the row number - mysql_data_seek(result->result, itor); - - // fetch the row - result->row.row = mysql_fetch_row(result->result); - tb_assert_and_check_return_val(result->row.row, tb_null); - - // fetch the lengths - result->row.lengths = mysql_fetch_lengths(result->result); - tb_assert_and_check_return_val(result->row.lengths, tb_null); - } - } - - // the row iterator - return (tb_pointer_t)&result->row; -} -static tb_size_t tb_database_mysql_result_col_iterator_size(tb_iterator_ref_t iterator) -{ - // check - tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator; - tb_assert_and_check_return_val(row, 0); - - // size - return row->count; -} -static tb_size_t tb_database_mysql_result_col_iterator_head(tb_iterator_ref_t iterator) -{ - // check - tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator; - tb_assert_and_check_return_val(row, 0); - - // head - return 0; -} -static tb_size_t tb_database_mysql_result_col_iterator_tail(tb_iterator_ref_t iterator) -{ - // check - tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator; - tb_assert_and_check_return_val(row, 0); - - // tail - return row->count; -} -static tb_size_t tb_database_mysql_result_col_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator; - tb_assert_and_check_return_val(row && itor && itor <= row->count, 0); - - // prev - return itor - 1; -} -static tb_size_t tb_database_mysql_result_col_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator; - tb_assert_and_check_return_val(row && itor < row->count, row->count); - - // next - return itor + 1; -} -static tb_pointer_t tb_database_mysql_result_col_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_mysql_result_row_t* row = (tb_database_mysql_result_row_t*)iterator; - tb_assert_and_check_return_val(row && itor < row->count, tb_null); - - // the mysql - tb_database_mysql_t* mysql = (tb_database_mysql_t*)iterator->priv; - tb_assert_and_check_return_val(mysql && mysql->result.fields, tb_null); - - // the field - MYSQL_FIELD* field = &mysql->result.fields[itor]; - - // fetch column from statement - if (mysql->result.statement) - { - // check - tb_assert_and_check_return_val(mysql->bind_list && itor < mysql->bind_maxn, tb_null); - - // the result - MYSQL_BIND* result = &mysql->bind_list[itor]; - - // fetch column - if (mysql_stmt_fetch_column(mysql->result.statement, result, itor, 0)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(mysql->result.statement)); - - // trace - tb_trace_e("statement: fetch result failed at: %lu, field_type: %d, error[%d]: %s", itor, field->type, mysql_stmt_errno(mysql->result.statement), mysql_stmt_error(mysql->result.statement)); - return tb_null; - } - - // init value - tb_database_sql_value_name_set(&row->value, (tb_char_t const*)field->name); - switch (result->buffer_type) - { - case MYSQL_TYPE_STRING: - tb_database_sql_value_set_text(&row->value, (tb_char_t const*)result->buffer, (tb_size_t)*result->length); - break; - case MYSQL_TYPE_LONG: - tb_database_sql_value_set_int32(&row->value, *((tb_int32_t const*)result->buffer)); - break; - case MYSQL_TYPE_LONGLONG: - tb_database_sql_value_set_int64(&row->value, *((tb_int64_t const*)result->buffer)); - break; - case MYSQL_TYPE_SHORT: - tb_database_sql_value_set_int16(&row->value, *((tb_int16_t const*)result->buffer)); - break; - case MYSQL_TYPE_TINY: - tb_database_sql_value_set_int8(&row->value, *((tb_int8_t const*)result->buffer)); - break; - case MYSQL_TYPE_INT24: - tb_database_sql_value_set_int32(&row->value, tb_bits_get_s24_ne((tb_byte_t const*)result->buffer)); - break; - // note: the field type of text, tinyblob, blob and longblob always be blob - case MYSQL_TYPE_BLOB: - { - // text? - if (field->charsetnr != 63) - { - tb_database_sql_value_set_text(&row->value, (tb_char_t const*)result->buffer, (tb_size_t)*result->length); - } - // blob? - else - { - // blob8? - if ((tb_size_t)*result->length <= TB_MAXU8) - { - tb_database_sql_value_set_blob8(&row->value, (tb_byte_t const*)result->buffer, (tb_size_t)*result->length); - } - // blob16? - else if ((tb_size_t)*result->length <= TB_MAXU16) - { - tb_database_sql_value_set_blob16(&row->value, (tb_byte_t const*)result->buffer, (tb_size_t)*result->length); - } - // blob32? - else - { - tb_database_mysql_stream_impl_set_value(&row->value, mysql, result, itor); - } - } - } - break; - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - tb_database_mysql_stream_impl_set_value(&row->value, mysql, result, itor); - break; - case MYSQL_TYPE_TINY_BLOB: - tb_database_sql_value_set_blob8(&row->value, (tb_byte_t const*)result->buffer, (tb_size_t)*result->length); - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case MYSQL_TYPE_FLOAT: - tb_database_sql_value_set_float(&row->value, *((tb_float_t const*)result->buffer)); - break; - case MYSQL_TYPE_DOUBLE: - tb_database_sql_value_set_double(&row->value, *((tb_double_t const*)result->buffer)); - break; -#endif - case MYSQL_TYPE_NULL: - tb_database_sql_value_set_null(&row->value); - break; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_YEAR: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - tb_trace_e("statement: fetch result: not supported buffer type: %d", result->buffer_type); - return tb_null; - default: - tb_trace_e("statement: fetch result: unknown buffer type: %d", result->buffer_type); - return tb_null; - } - } - // fetch column from result - else - { - // check - tb_assert_and_check_return_val(row->row && row->lengths, tb_null); - - // init value - tb_database_sql_value_name_set(&row->value, (tb_char_t const*)field->name); - tb_database_sql_value_set_text(&row->value, (tb_char_t const*)row->row[itor], (tb_size_t)row->lengths[itor]); - } - - // the col item - return (tb_pointer_t)&row->value; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_database_mysql_t* tb_database_mysql_cast(tb_database_sql_impl_t* database) -{ - // check - tb_assert_and_check_return_val(database && database->type == TB_DATABASE_SQL_TYPE_MYSQL, tb_null); - - // cast - return (tb_database_mysql_t*)database; -} -static tb_bool_t tb_database_mysql_open(tb_database_sql_impl_t* database) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return_val(mysql, tb_false); - - // done - tb_bool_t ok = tb_false; - tb_char_t const* host = tb_null; - tb_size_t port = 0; - tb_char_t username[64] = {0}; - tb_char_t password[64] = {0}; - tb_char_t database_sql_name[64] = {0}; - do - { - // the database host - host = tb_url_host(&database->url); - tb_assert_and_check_break(host); - - // the database port - port = tb_url_port(&database->url); - - // the database args - tb_char_t const* args = tb_url_args(&database->url); - if (args) - { - // the args size - tb_size_t argn = tb_strlen(args); - - // the database username - tb_char_t const* p = tb_stristr(args, "username="); - if (p) - { - // skip to value - p += 9; - - // the value end - tb_char_t const* e = tb_strchr(p, '&'); - if (!e) e = args + argn; - - // save username - if (p < e) tb_strlcpy(username, p, tb_min((e - p) + 1, sizeof(username))); - } - - // the database password - p = tb_stristr(args, "password="); - if (p) - { - // skip to value - p += 9; - - // the value end - tb_char_t const* e = tb_strchr(p, '&'); - if (!e) e = args + argn; - - // save password - if (p < e) tb_strlcpy(password, p, tb_min((e - p) + 1, sizeof(password))); - } - - // the database name - p = tb_stristr(args, "database="); - if (p) - { - // skip to value - p += 9; - - // the value end - tb_char_t const* e = tb_strchr(p, '&'); - if (!e) e = args + argn; - - // save database name - if (p < e) tb_strlcpy(database_sql_name, p, tb_min((e - p) + 1, sizeof(database_sql_name))); - } - } - - // load mysql library - if (!tb_database_mysql_library_load()) break; - - // init mysql database - mysql->database = mysql_init(tb_null); - tb_assert_and_check_break(mysql->database); - - // connect it - if (!mysql_real_connect(mysql->database, host, username[0]? username : tb_null, password[0]? password : tb_null, database_sql_name[0]? database_sql_name : tb_null, (tb_uint_t)port, tb_null, 0)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database)); - - // trace - tb_trace_e("open: host: %s failed, error[%d]: %s", host, mysql_errno(mysql->database), mysql_error(mysql->database)); - break; - } - - // disable auto commit - if (mysql_autocommit(mysql->database, 0)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database)); - - // trace - tb_trace_e("open: disable auto commit failed, error[%d]: %s", mysql_errno(mysql->database), mysql_error(mysql->database)); - break; - } - - // ok - ok = tb_true; - - } while (0); - - // trace - tb_trace_d("open: host: %s, port: %lu, username: %s, password: %s, database: %s : %s", host, port, username, password, database_sql_name, ok? "ok" : "no"); - - // ok? - return ok; -} -static tb_void_t tb_database_mysql_clos(tb_database_sql_impl_t* database) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return(mysql); - - // clear bind data - tb_buffer_clear(&mysql->bind_data); - - // clear bind list - if (mysql->bind_list && mysql->bind_maxn) - tb_memset(mysql->bind_list, 0, mysql->bind_maxn * sizeof(MYSQL_BIND)); - - // close database - if (mysql->database) mysql_close(mysql->database); - mysql->database = tb_null; -} -static tb_void_t tb_database_mysql_exit(tb_database_sql_impl_t* database) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return(mysql); - - // close it first - tb_database_mysql_clos(database); - - // exit bind data - tb_buffer_exit(&mysql->bind_data); - - // exit bind list - if (mysql->bind_list) tb_free(mysql->bind_list); - mysql->bind_list = tb_null; - mysql->bind_maxn = 0; - - // exit url - tb_url_exit(&database->url); - - // exit it - tb_free(mysql); -} -/* begin mysql transaction - * - * @note - * the default storage engine MyIASM do not support transaction - * need enable InnoDB engine and set autocommit=0 if you want to use it - */ -static tb_bool_t tb_database_mysql_begin(tb_database_sql_impl_t* database) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return_val(mysql && mysql->database, tb_false); - - // done begin - if (mysql_query(mysql->database, "begin;")) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database)); - - // trace - tb_trace_e("begin: failed, error[%d]: %s", mysql_errno(mysql->database), mysql_error(mysql->database)); - return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_database_mysql_commit(tb_database_sql_impl_t* database) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return_val(mysql && mysql->database, tb_false); - - // done commit - if (mysql_commit(mysql->database)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database)); - - // trace - tb_trace_e("commit: failed, error[%d]: %s", mysql_errno(mysql->database), mysql_error(mysql->database)); - return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_database_mysql_rollback(tb_database_sql_impl_t* database) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return_val(mysql && mysql->database, tb_false); - - // done rollback - if (mysql_rollback(mysql->database)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database)); - - // trace - tb_trace_e("rollback: failed, error[%d]: %s", mysql_errno(mysql->database), mysql_error(mysql->database)); - return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_database_mysql_done(tb_database_sql_impl_t* database, tb_char_t const* sql) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return_val(mysql && mysql->database && sql, tb_false); - - // exit the last result first - tb_database_mysql_result_exit(database, (tb_iterator_ref_t)&mysql->result); - - // done query - if (mysql_query(mysql->database, sql)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database)); - - // trace - tb_trace_e("done: sql: %s failed, error[%d]: %s", sql, mysql_errno(mysql->database), mysql_error(mysql->database)); - return tb_false; - } - - // trace - tb_trace_d("done: sql: %s: ok", sql); - - // ok - return tb_true; -} -static tb_void_t tb_database_mysql_result_exit(tb_database_sql_impl_t* database, tb_iterator_ref_t result) -{ - // check - tb_database_mysql_result_t* mysql_result = (tb_database_mysql_result_t*)result; - tb_assert_and_check_return(mysql_result); - - // exit stream - if (mysql_result->stream) tb_stream_exit(mysql_result->stream); - mysql_result->stream = tb_null; - - // exit result - if (mysql_result->result) mysql_free_result(mysql_result->result); - mysql_result->result = tb_null; - mysql_result->fields = tb_null; - - // clear result - mysql_result->count = 0; - mysql_result->row.count = 0; - - // exit metadata - if (mysql_result->metadata) mysql_free_result(mysql_result->metadata); - mysql_result->metadata = tb_null; - - // clear statement - if (mysql_result->statement && mysql_result->try_all) - mysql_stmt_free_result(mysql_result->statement); - mysql_result->statement = tb_null; - - // reset try all - mysql_result->try_all = tb_false; -} -static tb_size_t tb_database_mysql_result_type_size(tb_size_t type) -{ - // done - tb_size_t size = 0; - switch (type) - { - case MYSQL_TYPE_STRING: size = 8192; break; - case MYSQL_TYPE_LONG: size = 4; break; - case MYSQL_TYPE_LONGLONG: size = 8; break; - case MYSQL_TYPE_SHORT: size = 2; break; - case MYSQL_TYPE_TINY: size = 1; break; - case MYSQL_TYPE_INT24: size = 3; break; - // TODO: for text and tinyblob - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: size = 65536; break; - case MYSQL_TYPE_TINY_BLOB: size = 256; break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case MYSQL_TYPE_FLOAT: size = 4; break; - case MYSQL_TYPE_DOUBLE: size = 8; break; -#endif - case MYSQL_TYPE_NULL: break; - case MYSQL_TYPE_DECIMAL: - case MYSQL_TYPE_TIMESTAMP: - case MYSQL_TYPE_DATE: - case MYSQL_TYPE_TIME: - case MYSQL_TYPE_DATETIME: - case MYSQL_TYPE_YEAR: - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - tb_trace_e("not supported field type: %d", type); - break; - default: - tb_trace_e("unknown field type: %d", type); - break; - } - - // ok? - return size; -} -static tb_size_t tb_database_mysql_result_bind_maxn(tb_database_mysql_t* mysql) -{ - // check - tb_assert_and_check_return_val(mysql && mysql->result.statement && mysql->result.fields, 0); - - // walk - tb_size_t i = 0; - tb_size_t m = 0; - tb_size_t n = mysql->result.row.count; - for (i = 0; i < n; i++) - { - // += buffer - m += tb_database_mysql_result_type_size(mysql->result.fields[i].type); - - // += length - m += sizeof(tb_ulong_t); - - // += is_null - m += sizeof(my_bool); - } - - // ok? - return m; -} -static tb_bool_t tb_database_mysql_result_bind_data(tb_database_mysql_t* mysql) -{ - // check - tb_assert_and_check_return_val(mysql && mysql->result.statement && mysql->result.fields, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // check - tb_assert_and_check_break(mysql->bind_list && mysql->result.row.count <= mysql->bind_maxn); - - // the bind data and maxn - tb_byte_t* bind_data = tb_buffer_data(&mysql->bind_data); - tb_size_t bind_maxn = tb_buffer_maxn(&mysql->bind_data); - tb_assert_and_check_break(bind_data && bind_maxn); - - // clear data - tb_memset(bind_data, 0, bind_maxn); - - // bind data - tb_size_t i = 0; - tb_size_t n = mysql->result.row.count; - tb_byte_t* p = bind_data; - tb_byte_t* e = bind_data + bind_maxn; - for (i = 0; i < n; i++) - { - // the bind - MYSQL_BIND* bind = &mysql->bind_list[i]; - - // bind type - bind->buffer_type = mysql->result.fields[i].type; - - // bind buffer length - bind->buffer_length = (tb_ulong_t)tb_database_mysql_result_type_size(bind->buffer_type); - - // bind buffer - tb_assert_and_check_break(p + bind->buffer_length < e); - bind->buffer = bind->buffer_length? (tb_char_t*)p : tb_null; - p += bind->buffer_length; - - // bind is_unsigned - bind->is_unsigned = (mysql->result.fields[i].flags & UNSIGNED_FLAG)? 1 : 0; - - // bind length - tb_assert_and_check_break(p + sizeof(tb_ulong_t) < e); - bind->length = (tb_ulong_t*)p; - p += sizeof(tb_ulong_t); - - // bind is_null - tb_assert_and_check_break(p + sizeof(my_bool) < e); - bind->is_null = (my_bool*)p; - p += sizeof(my_bool); - } - - // check - tb_assert_and_check_break(i == n); - - // bind result - if (mysql_stmt_bind_result(mysql->result.statement, mysql->bind_list)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(mysql->result.statement)); - - // trace - tb_trace_e("statement: bind result failed, error[%d]: %s", mysql_stmt_errno(mysql->result.statement), mysql_stmt_error(mysql->result.statement)); - break; - } - - // ok - ok = tb_true; - - } while (0); - - // ok? - return ok; -} -static tb_bool_t tb_database_mysql_result_bind(tb_database_mysql_t* mysql, tb_bool_t try_all) -{ - // check - tb_assert_and_check_return_val(mysql && mysql->result.statement, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // load the field infos - mysql->result.metadata = mysql_stmt_result_metadata(mysql->result.statement); - tb_check_break(mysql->result.metadata); - - // save result col count - mysql->result.row.count = (tb_size_t)mysql_num_fields(mysql->result.metadata); - tb_assert_and_check_break(mysql->result.row.count); - - // load result fields - mysql->result.fields = mysql_fetch_fields(mysql->result.metadata); - tb_assert_and_check_break(mysql->result.fields); - - // make bind list - if (!mysql->bind_list) - { - mysql->bind_maxn = mysql->result.row.count + 16; - mysql->bind_list = (MYSQL_BIND*)tb_nalloc(mysql->bind_maxn, sizeof(MYSQL_BIND)); - } - // grow bind list - else if (mysql->result.row.count > mysql->bind_maxn) - { - mysql->bind_maxn = mysql->result.row.count + 16; - mysql->bind_list = (MYSQL_BIND*)tb_ralloc(mysql->bind_list, mysql->bind_maxn * sizeof(MYSQL_BIND)); - } - - // check - tb_assert_and_check_break(mysql->bind_list && mysql->result.row.count <= mysql->bind_maxn); - - // clear bind list - tb_memset(mysql->bind_list, 0, mysql->bind_maxn * sizeof(MYSQL_BIND)); - - // compute bind maxn - tb_size_t bind_maxn = tb_database_mysql_result_bind_maxn(mysql); - tb_assert_and_check_break(bind_maxn); - - // resize bind data - if (!tb_buffer_resize(&mysql->bind_data, bind_maxn)) break; - - // bind result data - if (!tb_database_mysql_result_bind_data(mysql)) break; - - // load all? - if (try_all && mysql_stmt_store_result(mysql->result.statement)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(mysql->result.statement)); - - // trace - tb_trace_e("statement: load all result failed, error[%d]: %s", mysql_stmt_errno(mysql->result.statement), mysql_stmt_error(mysql->result.statement)); - break; - } - - // try loading all? - mysql->result.try_all = try_all; - - // save result row count - mysql->result.count = try_all? (tb_size_t)mysql_stmt_num_rows(mysql->result.statement) : -1; - - // init mode - mysql->result.itor.mode = (try_all? TB_ITERATOR_MODE_RACCESS : TB_ITERATOR_MODE_FORWARD) | TB_ITERATOR_MODE_READONLY; - - // ok - ok = tb_true; - - } while (0); - - // ok? - return ok; -} -static tb_iterator_ref_t tb_database_mysql_result_load(tb_database_sql_impl_t* database, tb_bool_t try_all) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return_val(mysql && mysql->database, tb_null); - - // done - tb_bool_t ok = tb_false; - do - { - // load result from statement - if (mysql->result.statement) - { - // bind result - if (!tb_database_mysql_result_bind(mysql, try_all)) break; - - // try fetching the first result - if (!try_all) - { - // fetch the first row - tb_int_t ok = 0; - if ((ok = mysql_stmt_fetch(mysql->result.statement))) - { - // end or error? - if (ok != MYSQL_DATA_TRUNCATED) - { - // error? - if (ok != MYSQL_NO_DATA) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(mysql->result.statement)); - - // trace - tb_trace_e("statement: fetch row head failed, error[%d]: %s", mysql_stmt_errno(mysql->result.statement), mysql_stmt_error(mysql->result.statement)); - } - break; - } - } - } - } - else - { - // load result - mysql->result.result = try_all? mysql_store_result(mysql->database) : mysql_use_result(mysql->database); - tb_check_break(mysql->result.result); - - // try fetching the first result - if (!try_all) - { - // fetch the first row - mysql->result.row.row = mysql_fetch_row(mysql->result.result); - tb_check_break(mysql->result.row.row); - - // fetch the first lengths - mysql->result.row.lengths = mysql_fetch_lengths(mysql->result.result); - tb_assert_and_check_break(mysql->result.row.lengths); - } - - // load result fields - mysql->result.fields = mysql_fetch_fields(mysql->result.result); - tb_assert_and_check_break(mysql->result.fields); - - // save result row count - mysql->result.count = try_all? (tb_size_t)mysql_num_rows(mysql->result.result) : -1; - - // save result col count - mysql->result.row.count = (tb_size_t)mysql_num_fields(mysql->result.result); - - // try loading all? - mysql->result.try_all = try_all; - - // init mode - mysql->result.itor.mode = (try_all? TB_ITERATOR_MODE_RACCESS : TB_ITERATOR_MODE_FORWARD) | TB_ITERATOR_MODE_READONLY; - } - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit result - tb_database_mysql_result_exit(database, (tb_iterator_ref_t)&mysql->result); - } - - // ok? - return ok? (tb_iterator_ref_t)&mysql->result : tb_null; -} -static tb_database_sql_statement_ref_t tb_database_mysql_statement_init(tb_database_sql_impl_t* database, tb_char_t const* sql) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return_val(mysql && mysql->database && sql, tb_null); - - // done - tb_bool_t ok = tb_false; - MYSQL_STMT* statement = tb_null; - do - { - // init statement - statement = mysql_stmt_init(mysql->database); - if (!statement) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_errno(mysql->database)); - - // trace - tb_trace_e("statement: init: %s failed, error[%d]: %s", sql, mysql_errno(mysql->database), mysql_error(mysql->database)); - break; - } - - // prepare statement - if (mysql_stmt_prepare(statement, sql, tb_strlen(sql))) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno(statement)); - - // trace - tb_trace_e("statement: prepare: %s failed, error[%d]: %s", sql, mysql_stmt_errno(statement), mysql_stmt_error(statement)); - break; - } - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (statement) mysql_stmt_close(statement); - statement = tb_null; - } - - // ok? - return (tb_database_sql_statement_ref_t)statement; -} -static tb_void_t tb_database_mysql_statement_exit(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement) -{ - // exit it - if (statement) mysql_stmt_close((MYSQL_STMT*)statement); -} -static tb_bool_t tb_database_mysql_statement_done(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return_val(mysql && mysql->database && statement, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // exit the last result first - tb_database_mysql_result_exit(database, (tb_iterator_ref_t)&mysql->result); - - // done statement - if (mysql_stmt_execute((MYSQL_STMT*)statement)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno((MYSQL_STMT*)statement)); - - // trace - tb_trace_e("statement: done failed, error[%d]: %s", mysql_stmt_errno((MYSQL_STMT*)statement), mysql_stmt_error((MYSQL_STMT*)statement)); - break; - } - - // save statement - mysql->result.statement = (MYSQL_STMT*)statement; - - // ok - ok = tb_true; - - } while (0); - - // ok? - return ok; -} -static tb_bool_t tb_database_mysql_statement_bind(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size) -{ - // check - tb_database_mysql_t* mysql = tb_database_mysql_cast(database); - tb_assert_and_check_return_val(mysql && mysql->database && statement && list && size, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // check the param count - tb_size_t param_count = mysql_stmt_param_count((MYSQL_STMT*)statement); - tb_assert_and_check_break(size == param_count); - - // make bind list - if (!mysql->bind_list) - { - mysql->bind_maxn = size + 16; - mysql->bind_list = (MYSQL_BIND*)tb_nalloc(mysql->bind_maxn, sizeof(MYSQL_BIND)); - } - // grow bind list - else if (size > mysql->bind_maxn) - { - mysql->bind_maxn = size + 16; - mysql->bind_list = (MYSQL_BIND*)tb_ralloc(mysql->bind_list, mysql->bind_maxn * sizeof(MYSQL_BIND)); - } - - // check - tb_assert_and_check_break(mysql->bind_list && size <= mysql->bind_maxn); - - // clear bind list - tb_memset(mysql->bind_list, 0, mysql->bind_maxn * sizeof(MYSQL_BIND)); - - // init bind list - tb_size_t i = 0; - for (i = 0; i < size; i++) - { - // the value - tb_database_sql_value_t const* value = &list[i]; - switch (value->type) - { - case TB_DATABASE_SQL_VALUE_TYPE_TEXT: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_STRING; - mysql->bind_list[i].buffer = (tb_char_t*)tb_database_sql_value_text(value); - mysql->bind_list[i].buffer_length = tb_database_sql_value_size(value) + 1; - break; - case TB_DATABASE_SQL_VALUE_TYPE_INT64: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONGLONG; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.i64; - break; - case TB_DATABASE_SQL_VALUE_TYPE_INT32: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONG; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.i32; - break; - case TB_DATABASE_SQL_VALUE_TYPE_INT16: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_SHORT; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.i16; - break; - case TB_DATABASE_SQL_VALUE_TYPE_INT8: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_TINY; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.i8; - break; - case TB_DATABASE_SQL_VALUE_TYPE_UINT64: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONGLONG; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.u64; - mysql->bind_list[i].is_unsigned = 1; - break; - case TB_DATABASE_SQL_VALUE_TYPE_UINT32: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONG; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.u32; - mysql->bind_list[i].is_unsigned = 1; - break; - case TB_DATABASE_SQL_VALUE_TYPE_UINT16: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_SHORT; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.u16; - mysql->bind_list[i].is_unsigned = 1; - break; - case TB_DATABASE_SQL_VALUE_TYPE_UINT8: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_TINY; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.u8; - mysql->bind_list[i].is_unsigned = 1; - break; - case TB_DATABASE_SQL_VALUE_TYPE_BLOB32: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_LONG_BLOB; - mysql->bind_list[i].buffer = (tb_char_t*)tb_database_sql_value_blob(value); - mysql->bind_list[i].buffer_length = tb_database_sql_value_size(value); - mysql->bind_list[i].length = &mysql->bind_list[i].buffer_length; - break; - case TB_DATABASE_SQL_VALUE_TYPE_BLOB16: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_BLOB; - mysql->bind_list[i].buffer = (tb_char_t*)tb_database_sql_value_blob(value); - mysql->bind_list[i].buffer_length = tb_database_sql_value_size(value); - mysql->bind_list[i].length = &mysql->bind_list[i].buffer_length; - break; - case TB_DATABASE_SQL_VALUE_TYPE_BLOB8: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_TINY_BLOB; - mysql->bind_list[i].buffer = (tb_char_t*)tb_database_sql_value_blob(value); - mysql->bind_list[i].buffer_length = tb_database_sql_value_size(value); - mysql->bind_list[i].length = &mysql->bind_list[i].buffer_length; - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_DATABASE_SQL_VALUE_TYPE_FLOAT: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_FLOAT; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.f; - break; - case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_DOUBLE; - mysql->bind_list[i].buffer = (tb_char_t*)&value->u.d; - break; -#endif - case TB_DATABASE_SQL_VALUE_TYPE_NULL: - mysql->bind_list[i].buffer_type = MYSQL_TYPE_NULL; - break; - default: - tb_trace_e("statement: bind: unknown value type: %lu", value->type); - break; - } - } - - // bind it - if (mysql_stmt_bind_param((MYSQL_STMT*)statement, mysql->bind_list)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno((MYSQL_STMT*)statement)); - - // trace - tb_trace_e("statement: bind failed, error[%d]: %s", mysql_stmt_errno((MYSQL_STMT*)statement), mysql_stmt_error((MYSQL_STMT*)statement)); - break; - } - - // send blob32 data - tb_byte_t data[TB_STREAM_BLOCK_MAXN]; - for (i = 0; i < size; i++) - { - // the value - tb_database_sql_value_t const* value = &list[i]; - if (value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB32 && value->u.blob.stream) - { - // trace - tb_trace_d("statement: bind: send: blob: %lld: ..", tb_stream_size(value->u.blob.stream)); - - // done - while (!tb_stream_beof(value->u.blob.stream)) - { - // read it - tb_long_t real = tb_stream_read(value->u.blob.stream, data, sizeof(data)); - if (real > 0) - { - // send it - if (mysql_stmt_send_long_data((MYSQL_STMT*)statement, i, (tb_char_t const*)data, real)) - { - // save state - mysql->base.state = tb_database_mysql_state_from_errno(mysql_stmt_errno((MYSQL_STMT*)statement)); - - // trace - tb_trace_e("statement: bind: send blob data failed, error[%d]: %s", mysql_stmt_errno((MYSQL_STMT*)statement), mysql_stmt_error((MYSQL_STMT*)statement)); - break; - } - } - else if (!real) - { - // wait - tb_long_t wait = tb_stream_wait(value->u.blob.stream, TB_STREAM_WAIT_READ, tb_stream_timeout(value->u.blob.stream)); - tb_assert_and_check_break(wait > 0); - } - else break; - } - } - } - - // ok - ok = tb_true; - - } while (0); - - // ok? - return ok; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_size_t tb_database_mysql_probe(tb_url_ref_t url) -{ - // check - tb_assert_and_check_return_val(url, 0); - - // done - tb_size_t score = 0; - do - { - // the url arguments - tb_char_t const* args = tb_url_args(url); - if (args) - { - // find the database type - tb_char_t const* ptype = tb_stristr(args, "type="); - if (ptype && !tb_strnicmp(ptype + 5, "mysql", 5)) - { - // ok - score = 100; - break; - } - } - - // the database port, the default port: 3306 - if (tb_url_port(url) == 3306) score += 20; - - // is sql url? - if (tb_url_protocol(url) == TB_URL_PROTOCOL_SQL) - score += 5; - - } while (0); - - // trace - tb_trace_d("probe: %s, score: %lu", tb_url_cstr((tb_url_ref_t)url), score); - - // ok? - return score; -} -tb_database_sql_ref_t tb_database_mysql_init(tb_url_ref_t url) -{ - // check - tb_assert_and_check_return_val(url, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_database_mysql_t* mysql = tb_null; - do - { - // make database - mysql = tb_malloc0_type(tb_database_mysql_t); - tb_assert_and_check_break(mysql); - - // init database - mysql->base.type = TB_DATABASE_SQL_TYPE_MYSQL; - mysql->base.open = tb_database_mysql_open; - mysql->base.clos = tb_database_mysql_clos; - mysql->base.exit = tb_database_mysql_exit; - mysql->base.done = tb_database_mysql_done; - mysql->base.begin = tb_database_mysql_begin; - mysql->base.commit = tb_database_mysql_commit; - mysql->base.rollback = tb_database_mysql_rollback; - mysql->base.result_load = tb_database_mysql_result_load; - mysql->base.result_exit = tb_database_mysql_result_exit; - mysql->base.statement_init = tb_database_mysql_statement_init; - mysql->base.statement_exit = tb_database_mysql_statement_exit; - mysql->base.statement_done = tb_database_mysql_statement_done; - mysql->base.statement_bind = tb_database_mysql_statement_bind; - - // init result row iterator - mysql->result.itor.mode = TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_READONLY; - mysql->result.itor.priv = (tb_pointer_t)mysql; - mysql->result.itor.step = 0; - mysql->result.itor.size = tb_database_mysql_result_row_iterator_size; - mysql->result.itor.head = tb_database_mysql_result_row_iterator_head; - mysql->result.itor.tail = tb_database_mysql_result_row_iterator_tail; - mysql->result.itor.prev = tb_database_mysql_result_row_iterator_prev; - mysql->result.itor.next = tb_database_mysql_result_row_iterator_next; - mysql->result.itor.item = tb_database_mysql_result_row_iterator_item; - mysql->result.itor.copy = tb_null; - mysql->result.itor.comp = tb_null; - - // init result col iterator - mysql->result.row.itor.mode = TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_READONLY; - mysql->result.row.itor.priv = (tb_pointer_t)mysql; - mysql->result.row.itor.step = 0; - mysql->result.row.itor.size = tb_database_mysql_result_col_iterator_size; - mysql->result.row.itor.head = tb_database_mysql_result_col_iterator_head; - mysql->result.row.itor.tail = tb_database_mysql_result_col_iterator_tail; - mysql->result.row.itor.prev = tb_database_mysql_result_col_iterator_prev; - mysql->result.row.itor.next = tb_database_mysql_result_col_iterator_next; - mysql->result.row.itor.item = tb_database_mysql_result_col_iterator_item; - mysql->result.row.itor.copy = tb_null; - mysql->result.row.itor.comp = tb_null; - - // init url - if (!tb_url_init(&mysql->base.url)) break; - - // copy url - tb_url_copy(&mysql->base.url, url); - - // init state - mysql->base.state = TB_STATE_OK; - - // init bind - if (!tb_buffer_init(&mysql->bind_data)) break; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit database - if (mysql) tb_database_mysql_exit((tb_database_sql_impl_t*)mysql); - mysql = tb_null; - } - - // ok? - return (tb_database_sql_ref_t)mysql; -} - diff --git a/core/src/tbox/src/tbox/database/impl/mysql.h b/core/src/tbox/src/tbox/database/impl/mysql.h deleted file mode 100644 index 2856df9ec..000000000 --- a/core/src/tbox/src/tbox/database/impl/mysql.h +++ /dev/null @@ -1,62 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file mysql.h - */ -#ifndef TB_DATABASE_IMPL_MYSQL_H -#define TB_DATABASE_IMPL_MYSQL_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* probe mysql from the url - * - * @param url the database url - * - * @return the score - */ -tb_size_t tb_database_mysql_probe(tb_url_ref_t url); - -/* init mysql - * - * @param url the database url - * - * @return the database handle - */ -tb_database_sql_ref_t tb_database_mysql_init(tb_url_ref_t url); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/database/impl/prefix.h b/core/src/tbox/src/tbox/database/impl/prefix.h deleted file mode 100644 index 071678ed6..000000000 --- a/core/src/tbox/src/tbox/database/impl/prefix.h +++ /dev/null @@ -1,97 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_DATABASE_IMPL_PREFIX_H -#define TB_DATABASE_IMPL_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../sql.h" -#include "sqlite3.h" -#include "mysql.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the database sql impl type -typedef struct __tb_database_sql_impl_t -{ - // the url - tb_url_t url; - - // the type - tb_size_t type; - - // the state - tb_size_t state; - - // is opened? - tb_bool_t bopened; - - // open - tb_bool_t (*open)(struct __tb_database_sql_impl_t* database); - - // clos - tb_void_t (*clos)(struct __tb_database_sql_impl_t* database); - - // exit - tb_void_t (*exit)(struct __tb_database_sql_impl_t* database); - - // done - tb_bool_t (*done)(struct __tb_database_sql_impl_t* database, tb_char_t const* sql); - - // begin - tb_bool_t (*begin)(struct __tb_database_sql_impl_t* database); - - // commit - tb_bool_t (*commit)(struct __tb_database_sql_impl_t* database); - - // rollback - tb_bool_t (*rollback)(struct __tb_database_sql_impl_t* database); - - // load result - tb_iterator_ref_t (*result_load)(struct __tb_database_sql_impl_t* database, tb_bool_t try_all); - - // exit result - tb_void_t (*result_exit)(struct __tb_database_sql_impl_t* database, tb_iterator_ref_t result); - - // statement init - tb_database_sql_statement_ref_t (*statement_init)(struct __tb_database_sql_impl_t* database, tb_char_t const* sql); - - // statement exit - tb_void_t (*statement_exit)(struct __tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement); - - // statement done - tb_bool_t (*statement_done)(struct __tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement); - - // statement bind - tb_bool_t (*statement_bind)(struct __tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size); - -}tb_database_sql_impl_t; - - -#endif diff --git a/core/src/tbox/src/tbox/database/impl/sqlite3.c b/core/src/tbox/src/tbox/database/impl/sqlite3.c deleted file mode 100644 index edbdf5a63..000000000 --- a/core/src/tbox/src/tbox/database/impl/sqlite3.c +++ /dev/null @@ -1,935 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file sqlite3.c - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "sqlite3" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include <sqlite3.h> - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the sqlite3 result row type -typedef struct __tb_database_sqlite3_result_row_t -{ - // the iterator - tb_iterator_t itor; - - // the row - tb_size_t row; - - // the col count - tb_size_t count; - - // the col value - tb_database_sql_value_t value; - -}tb_database_sqlite3_result_row_t; - -// the sqlite3 result type -typedef struct __tb_database_sqlite3_result_t -{ - // the iterator - tb_iterator_t itor; - - // the result - tb_char_t** result; - - // the statement - sqlite3_stmt* statement; - - // the row count - tb_size_t count; - - // the row - tb_database_sqlite3_result_row_t row; - -}tb_database_sqlite3_result_t; - -// the sqlite3 type -typedef struct __tb_database_sqlite3_t -{ - // the base - tb_database_sql_impl_t base; - - // the database - sqlite3* database; - - // the result - tb_database_sqlite3_result_t result; - -}tb_database_sqlite3_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * library implementation - */ -static tb_handle_t tb_database_sqlite3_library_init(tb_cpointer_t* ppriv) -{ - // init it - tb_int_t ok = SQLITE_OK; - if ((ok = sqlite3_initialize()) != SQLITE_OK) - { - // trace - tb_trace_e("init: sqlite3 library failed, error: %d", ok); - return tb_null; - } - - // ok - return ppriv; -} -static tb_void_t tb_database_sqlite3_library_exit(tb_handle_t handle, tb_cpointer_t priv) -{ - // exit it - sqlite3_shutdown(); -} -static tb_handle_t tb_database_sqlite3_library_load() -{ - return tb_singleton_instance(TB_SINGLETON_TYPE_LIBRARY_SQLITE3, tb_database_sqlite3_library_init, tb_database_sqlite3_library_exit, tb_null, tb_null); -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * state implementation - */ -static tb_size_t tb_database_sqlite3_state_from_errno(tb_size_t errno) -{ - // done - tb_size_t state = TB_STATE_DATABASE_UNKNOWN_ERROR; - switch (errno) - { - case SQLITE_NOTADB: - state = TB_STATE_DATABASE_NO_SUCH_DATABASE; - break; - case SQLITE_PERM: - case SQLITE_AUTH: - state = TB_STATE_DATABASE_ACCESS_DENIED; - break; - case SQLITE_ERROR: - case SQLITE_INTERNAL: - break; - default: - tb_trace_e("unknown errno: %lu", errno); - break; - } - - // ok? - return state; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * iterator implementation - */ -static tb_size_t tb_database_sqlite3_result_row_iterator_size(tb_iterator_ref_t iterator) -{ - // check - tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator; - tb_assert(result); - - // size - return result->count; -} -static tb_size_t tb_database_sqlite3_result_row_iterator_head(tb_iterator_ref_t iterator) -{ - // head - return 0; -} -static tb_size_t tb_database_sqlite3_result_row_iterator_tail(tb_iterator_ref_t iterator) -{ - // check - tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator; - tb_assert(result); - - // tail - return result->count; -} -static tb_size_t tb_database_sqlite3_result_row_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator; - tb_assert(result); - tb_assert_and_check_return_val(itor && itor <= result->count, result->count); - - // cannot be the statement result - tb_assert_and_check_return_val(!result->statement, result->count); - - // prev - return itor - 1; -} -static tb_size_t tb_database_sqlite3_result_row_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator; - tb_assert(result); - tb_assert_and_check_return_val(itor < result->count, result->count); - - // statement result? - if (result->statement) - { - // step statement - tb_int_t ok = sqlite3_step(result->statement); - - // end? - if (ok != SQLITE_ROW) - { - // reset it - if (SQLITE_OK != sqlite3_reset(result->statement)) - { - // the sqlite - tb_database_sqlite3_t* sqlite = (tb_database_sqlite3_t*)iterator->priv; - if (sqlite) - { - // save state - sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); - - // trace - tb_trace_e("statement: reset failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); - } - } - - // tail - return result->count; - } - } - - // next - return itor + 1; -} -static tb_pointer_t tb_database_sqlite3_result_row_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_sqlite3_result_t* result = (tb_database_sqlite3_result_t*)iterator; - tb_assert_and_check_return_val(result && (result->result || result->statement) && itor < result->count, tb_null); - - // save the row - result->row.row = itor; - - // the row iterator - return (tb_pointer_t)&result->row; -} -static tb_size_t tb_database_sqlite3_result_col_iterator_size(tb_iterator_ref_t iterator) -{ - // check - tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator; - tb_assert_and_check_return_val(row, 0); - - // size - return row->count; -} -static tb_size_t tb_database_sqlite3_result_col_iterator_head(tb_iterator_ref_t iterator) -{ - // check - tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator; - tb_assert_and_check_return_val(row, 0); - - // head - return 0; -} -static tb_size_t tb_database_sqlite3_result_col_iterator_tail(tb_iterator_ref_t iterator) -{ - // check - tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator; - tb_assert_and_check_return_val(row, 0); - - // tail - return row->count; -} -static tb_size_t tb_database_sqlite3_result_col_iterator_prev(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator; - tb_assert_and_check_return_val(row && itor && itor <= row->count, 0); - - // prev - return itor - 1; -} -static tb_size_t tb_database_sqlite3_result_col_iterator_next(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator; - tb_assert_and_check_return_val(row && itor < row->count, row->count); - - // next - return itor + 1; -} -static tb_pointer_t tb_database_sqlite3_result_col_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor) -{ - // check - tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator; - tb_assert_and_check_return_val(row && itor < row->count, tb_null); - - // the sqlite - tb_database_sqlite3_t* sqlite = (tb_database_sqlite3_t*)iterator->priv; - tb_assert_and_check_return_val(sqlite, tb_null); - - // result? - if (sqlite->result.result) - { - // init value - tb_database_sql_value_name_set(&row->value, (tb_char_t const*)sqlite->result.result[itor]); - tb_database_sql_value_set_text(&row->value, (tb_char_t const*)sqlite->result.result[((1 + sqlite->result.row.row) * row->count) + itor], 0); - return (tb_pointer_t)&row->value; - } - // statement result? - else if (sqlite->result.statement) - { - // init name - tb_database_sql_value_name_set(&row->value, sqlite3_column_name(sqlite->result.statement, itor)); - - // init type - tb_size_t type = sqlite3_column_type(sqlite->result.statement, itor); - switch (type) - { - case SQLITE_INTEGER: - tb_database_sql_value_set_int32(&row->value, sqlite3_column_int(sqlite->result.statement, itor)); - break; - case SQLITE_TEXT: - tb_database_sql_value_set_text(&row->value, (tb_char_t const*)sqlite3_column_text(sqlite->result.statement, itor), sqlite3_column_bytes(sqlite->result.statement, itor)); - break; - case SQLITE_FLOAT: -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - tb_database_sql_value_set_double(&row->value, sqlite3_column_double(sqlite->result.statement, itor)); - break; -#else - // trace - tb_trace1_e("float type is not supported, at col: %lu, please enable float config!", itor); - return tb_null; -#endif - case SQLITE_BLOB: - tb_database_sql_value_set_blob32(&row->value, (tb_byte_t const*)sqlite3_column_blob(sqlite->result.statement, itor), sqlite3_column_bytes(sqlite->result.statement, itor), tb_null); - break; - case SQLITE_NULL: - tb_database_sql_value_set_null(&row->value); - break; - default: - tb_trace_e("unknown field type: %s, at col: %lu", type, itor); - return tb_null; - } - - // ok - return (tb_pointer_t)&row->value; - } - - // failed - tb_assert(0); - return tb_null; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_database_sqlite3_t* tb_database_sqlite3_cast(tb_database_sql_impl_t* database) -{ - // check - tb_assert_and_check_return_val(database && database->type == TB_DATABASE_SQL_TYPE_SQLITE3, tb_null); - - // cast - return (tb_database_sqlite3_t*)database; -} -static tb_bool_t tb_database_sqlite3_open(tb_database_sql_impl_t* database) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return_val(sqlite, tb_false); - - // done - tb_bool_t ok = tb_false; - tb_char_t const* path = tb_null; - do - { - // the database path - path = tb_url_cstr(&database->url); - tb_assert_and_check_break(path); - - // load sqlite3 library - if (!tb_database_sqlite3_library_load()) break; - - // open database - if (SQLITE_OK != sqlite3_open_v2(path, &sqlite->database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, tb_null) || !sqlite->database) - { - // error - if (sqlite->database) - { - // save state - sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); - - // trace - tb_trace_e("open: %s failed, error[%d]: %s", path, sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); - } - break; - } - - // ok - ok = tb_true; - - } while (0); - - // trace - tb_trace_d("open: %s: %s", path, ok? "ok" : "no"); - - // ok? - return ok; -} -static tb_void_t tb_database_sqlite3_clos(tb_database_sql_impl_t* database) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return(sqlite); - - // exit result first if exists - if (sqlite->result.result) sqlite3_free_table(sqlite->result.result); - sqlite->result.result = tb_null; - - // close database - if (sqlite->database) sqlite3_close(sqlite->database); - sqlite->database = tb_null; -} -static tb_void_t tb_database_sqlite3_exit(tb_database_sql_impl_t* database) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return(sqlite); - - // close it first - tb_database_sqlite3_clos(database); - - // exit url - tb_url_exit(&database->url); - - // exit it - tb_free(sqlite); -} -static tb_bool_t tb_database_sqlite3_begin(tb_database_sql_impl_t* database) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return_val(sqlite && sqlite->database, tb_false); - - // done commit - if (SQLITE_OK != sqlite3_exec(sqlite->database, "begin;", tb_null, tb_null, tb_null)) - { - // save state - sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); - - // trace - tb_trace_e("begin: failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); - return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_database_sqlite3_commit(tb_database_sql_impl_t* database) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return_val(sqlite && sqlite->database, tb_false); - - // done commit - if (SQLITE_OK != sqlite3_exec(sqlite->database, "commit;", tb_null, tb_null, tb_null)) - { - // save state - sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); - - // trace - tb_trace_e("commit: failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); - return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_database_sqlite3_rollback(tb_database_sql_impl_t* database) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return_val(sqlite && sqlite->database, tb_false); - - // done rollback - if (SQLITE_OK != sqlite3_exec(sqlite->database, "rollback;", tb_null, tb_null, tb_null)) - { - // save state - sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); - - // trace - tb_trace_e("rollback: failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); - return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_database_sqlite3_done(tb_database_sql_impl_t* database, tb_char_t const* sql) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return_val(sqlite && sqlite->database && sql, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // exit result first if exists - if (sqlite->result.result) sqlite3_free_table(sqlite->result.result); - sqlite->result.result = tb_null; - - // clear the lasr statement first - sqlite->result.statement = tb_null; - - // clear the result row count first - sqlite->result.count = 0; - - // clear the result col count first - sqlite->result.row.count = 0; - - // done sql - tb_int_t row_count = 0; - tb_int_t col_count = 0; - tb_char_t* error = tb_null; - if (SQLITE_OK != sqlite3_get_table(sqlite->database, sql, &sqlite->result.result, &row_count, &col_count, &error)) - { - // save state - sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); - - // trace - tb_trace_e("done: sql: %s failed, error[%d]: %s", sql, sqlite3_errcode(sqlite->database), error); - - // exit error - if (error) sqlite3_free(error); - break; - } - - // no result? - if (!row_count) - { - // exit result - if (sqlite->result.result) sqlite3_free_table(sqlite->result.result); - sqlite->result.result = tb_null; - - // trace - tb_trace_d("done: sql: %s: ok", sql); - - // ok - ok = tb_true; - break; - } - - // save the result iterator mode - sqlite->result.itor.mode = TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_READONLY; - - // save result row count - sqlite->result.count = row_count; - - // save result col count - sqlite->result.row.count = col_count; - - // trace - tb_trace_d("done: sql: %s: ok", sql); - - // ok - ok = tb_true; - - } while (0); - - // ok? - return ok; -} -static tb_void_t tb_database_sqlite3_result_exit(tb_database_sql_impl_t* database, tb_iterator_ref_t result) -{ - // check - tb_database_sqlite3_result_t* sqlite3_result = (tb_database_sqlite3_result_t*)result; - tb_assert_and_check_return(sqlite3_result); - - // exit result - if (sqlite3_result->result) sqlite3_free_table(sqlite3_result->result); - sqlite3_result->result = tb_null; - - // clear the statement - sqlite3_result->statement = tb_null; - - // clear result - sqlite3_result->count = 0; - sqlite3_result->row.count = 0; -} -static tb_iterator_ref_t tb_database_sqlite3_result_load(tb_database_sql_impl_t* database, tb_bool_t try_all) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return_val(sqlite && sqlite->database, tb_null); - - // ok? - return (sqlite->result.result || sqlite->result.statement)? (tb_iterator_ref_t)&sqlite->result : tb_null; -} -static tb_void_t tb_database_sqlite3_statement_exit(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement) -{ - // exit statement - if (statement) sqlite3_finalize((sqlite3_stmt*)statement); -} -static tb_database_sql_statement_ref_t tb_database_sqlite3_statement_init(tb_database_sql_impl_t* database, tb_char_t const* sql) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return_val(sqlite && sqlite->database && sql, tb_null); - - // init statement - sqlite3_stmt* statement = tb_null; - if (SQLITE_OK != sqlite3_prepare_v2(sqlite->database, sql, -1, &statement, 0)) - { - // save state - sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); - - // trace - tb_trace_e("statement: init %s failed, error[%d]: %s", sql, sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); - } - - // ok? - return (tb_database_sql_statement_ref_t)statement; -} -static tb_bool_t tb_database_sqlite3_statement_done(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return_val(sqlite && sqlite->database && statement, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // exit result first if exists - if (sqlite->result.result) sqlite3_free_table(sqlite->result.result); - sqlite->result.result = tb_null; - - // clear the last statement first - sqlite->result.statement = tb_null; - - // clear the result row count first - sqlite->result.count = 0; - - // clear the result col count first - sqlite->result.row.count = 0; - - // step statement - tb_int_t result = sqlite3_step((sqlite3_stmt*)statement); - tb_assert_and_check_break(result == SQLITE_DONE || result == SQLITE_ROW); - - // exists result? - if (result == SQLITE_ROW) - { - // save the result iterator mode - sqlite->result.itor.mode = TB_ITERATOR_MODE_FORWARD | TB_ITERATOR_MODE_READONLY; - - // save statement for iterating it - sqlite->result.statement = (sqlite3_stmt*)statement; - - // save result row count - sqlite->result.count = (tb_size_t)-1; - - // save result col count - sqlite->result.row.count = sqlite3_column_count((sqlite3_stmt*)statement); - } - else - { - // reset it - if (SQLITE_OK != sqlite3_reset((sqlite3_stmt*)statement)) - { - // save state - sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); - - // trace - tb_trace_e("statement: reset failed, error[%d]: %s", sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); - - // failed - break; - } - } - - // ok - ok = tb_true; - - } while (0); - - // ok? - return ok; -} -static tb_void_t tb_database_sqlite3_statement_bind_exit(tb_pointer_t data) -{ - // trace - tb_trace_d("bind: exit: %p", data); - - // exit it - if (data) tb_free(data); -} -static tb_bool_t tb_database_sqlite3_statement_bind(tb_database_sql_impl_t* database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size) -{ - // check - tb_database_sqlite3_t* sqlite = tb_database_sqlite3_cast(database); - tb_assert_and_check_return_val(sqlite && sqlite->database && statement && list && size, tb_false); - - // the param count - tb_size_t param_count = (tb_size_t)sqlite3_bind_parameter_count((sqlite3_stmt*)statement); - tb_assert_and_check_return_val(size == param_count, tb_false); - - // walk - tb_size_t i = 0; - for (i = 0; i < size; i++) - { - // the value - tb_database_sql_value_t const* value = &list[i]; - - // done - tb_int_t ok = SQLITE_ERROR; - tb_byte_t* data = tb_null; - switch (value->type) - { - case TB_DATABASE_SQL_VALUE_TYPE_TEXT: - tb_trace_i("sqlite3: test %lu %s", i, value->u.text.data); - ok = sqlite3_bind_text((sqlite3_stmt*)statement, (tb_int_t)(i + 1), value->u.text.data, (tb_int_t)tb_database_sql_value_size(value), tb_null); - break; - case TB_DATABASE_SQL_VALUE_TYPE_INT64: - case TB_DATABASE_SQL_VALUE_TYPE_UINT64: - ok = sqlite3_bind_int64((sqlite3_stmt*)statement, (tb_int_t)(i + 1), tb_database_sql_value_int64(value)); - break; - case TB_DATABASE_SQL_VALUE_TYPE_INT32: - case TB_DATABASE_SQL_VALUE_TYPE_INT16: - case TB_DATABASE_SQL_VALUE_TYPE_INT8: - case TB_DATABASE_SQL_VALUE_TYPE_UINT32: - case TB_DATABASE_SQL_VALUE_TYPE_UINT16: - case TB_DATABASE_SQL_VALUE_TYPE_UINT8: - ok = sqlite3_bind_int((sqlite3_stmt*)statement, (tb_int_t)(i + 1), (tb_int_t)tb_database_sql_value_int32(value)); - break; - case TB_DATABASE_SQL_VALUE_TYPE_BLOB16: - case TB_DATABASE_SQL_VALUE_TYPE_BLOB8: - ok = sqlite3_bind_blob((sqlite3_stmt*)statement, (tb_int_t)(i + 1), value->u.blob.data, (tb_int_t)value->u.blob.size, tb_null); - break; - case TB_DATABASE_SQL_VALUE_TYPE_BLOB32: - { - if (value->u.blob.stream) - { - // done - do - { - // the stream size - tb_hong_t size = tb_stream_size(value->u.blob.stream); - tb_assert_and_check_break(size >= 0); - - // make data - data = tb_malloc0_bytes((tb_size_t)size); - tb_assert_and_check_break(data); - - // read data - if (!tb_stream_bread(value->u.blob.stream, data, (tb_size_t)size)) break; - - // bind it - ok = sqlite3_bind_blob((sqlite3_stmt*)statement, (tb_int_t)(i + 1), data, (tb_int_t)size, tb_database_sqlite3_statement_bind_exit); - - } while (0); - } - else ok = sqlite3_bind_blob((sqlite3_stmt*)statement, (tb_int_t)(i + 1), value->u.blob.data, (tb_int_t)value->u.blob.size, tb_null); - } - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_DATABASE_SQL_VALUE_TYPE_FLOAT: - case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE: - ok = sqlite3_bind_double((sqlite3_stmt*)statement, (tb_int_t)(i + 1), (tb_double_t)tb_database_sql_value_double(value)); - break; -#endif - case TB_DATABASE_SQL_VALUE_TYPE_NULL: - ok = sqlite3_bind_null((sqlite3_stmt*)statement, (tb_int_t)(i + 1)); - break; - default: - tb_trace_e("statement: bind: unknown value type: %lu", value->type); - break; - } - - // failed? - if (SQLITE_OK != ok) - { - // exit data - if (data) tb_free(data); - data = tb_null; - - // save state - sqlite->base.state = tb_database_sqlite3_state_from_errno(sqlite3_errcode(sqlite->database)); - - // trace - tb_trace_e("statement: bind value[%lu] failed, error[%d]: %s", i, sqlite3_errcode(sqlite->database), sqlite3_errmsg(sqlite->database)); - break; - } - } - - // ok? - return (i == size)? tb_true : tb_false; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_size_t tb_database_sqlite3_probe(tb_url_ref_t url) -{ - // check - tb_assert_and_check_return_val(url, 0); - - // done - tb_size_t score = 0; - tb_stream_ref_t stream = tb_null; - do - { - // the url arguments - tb_char_t const* args = tb_url_args(url); - if (args) - { - // find the database type - tb_char_t const* ptype = tb_stristr(args, "type="); - if (ptype && !tb_strnicmp(ptype + 5, "sqlite3", 7)) - { - // ok - score = 100; - break; - } - } - - // has host or port? no sqlite3 - if (tb_url_host(url) || tb_url_port(url)) break; - - // the database path - tb_char_t const* path = tb_url_cstr((tb_url_ref_t)url); - tb_assert_and_check_break(path); - - // is file? - if (tb_url_protocol(url) == TB_URL_PROTOCOL_FILE) score += 20; - - // init stream - stream = tb_stream_init_from_url(path); - tb_assert_and_check_break(stream); - - // open stream - if (!tb_stream_open(stream)) break; - - // read head - tb_char_t head[16] = {0}; - if (!tb_stream_bread(stream, (tb_byte_t*)head, 15)) break; - - // is sqlite3? - if (!tb_stricmp(head, "SQLite format 3")) score = 100; - - } while (0); - - // exit stream - if (stream) tb_stream_exit(stream); - stream = tb_null; - - // trace - tb_trace_d("probe: %s, score: %lu", tb_url_cstr((tb_url_ref_t)url), score); - - // ok? - return score; -} -tb_database_sql_ref_t tb_database_sqlite3_init(tb_url_ref_t url) -{ - // check - tb_assert_and_check_return_val(url, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_database_sqlite3_t* sqlite = tb_null; - do - { - // make database - sqlite = tb_malloc0_type(tb_database_sqlite3_t); - tb_assert_and_check_break(sqlite); - - // init database - sqlite->base.type = TB_DATABASE_SQL_TYPE_SQLITE3; - sqlite->base.open = tb_database_sqlite3_open; - sqlite->base.clos = tb_database_sqlite3_clos; - sqlite->base.exit = tb_database_sqlite3_exit; - sqlite->base.done = tb_database_sqlite3_done; - sqlite->base.begin = tb_database_sqlite3_begin; - sqlite->base.commit = tb_database_sqlite3_commit; - sqlite->base.rollback = tb_database_sqlite3_rollback; - sqlite->base.result_load = tb_database_sqlite3_result_load; - sqlite->base.result_exit = tb_database_sqlite3_result_exit; - sqlite->base.statement_init = tb_database_sqlite3_statement_init; - sqlite->base.statement_exit = tb_database_sqlite3_statement_exit; - sqlite->base.statement_done = tb_database_sqlite3_statement_done; - sqlite->base.statement_bind = tb_database_sqlite3_statement_bind; - - // init result row iterator - sqlite->result.itor.mode = 0; - sqlite->result.itor.priv = (tb_pointer_t)sqlite; - sqlite->result.itor.step = 0; - sqlite->result.itor.size = tb_database_sqlite3_result_row_iterator_size; - sqlite->result.itor.head = tb_database_sqlite3_result_row_iterator_head; - sqlite->result.itor.tail = tb_database_sqlite3_result_row_iterator_tail; - sqlite->result.itor.prev = tb_database_sqlite3_result_row_iterator_prev; - sqlite->result.itor.next = tb_database_sqlite3_result_row_iterator_next; - sqlite->result.itor.item = tb_database_sqlite3_result_row_iterator_item; - sqlite->result.itor.copy = tb_null; - sqlite->result.itor.comp = tb_null; - - // init result col iterator - sqlite->result.row.itor.mode = TB_ITERATOR_MODE_RACCESS | TB_ITERATOR_MODE_READONLY; - sqlite->result.row.itor.priv = (tb_pointer_t)sqlite; - sqlite->result.row.itor.step = 0; - sqlite->result.row.itor.size = tb_database_sqlite3_result_col_iterator_size; - sqlite->result.row.itor.head = tb_database_sqlite3_result_col_iterator_head; - sqlite->result.row.itor.tail = tb_database_sqlite3_result_col_iterator_tail; - sqlite->result.row.itor.prev = tb_database_sqlite3_result_col_iterator_prev; - sqlite->result.row.itor.next = tb_database_sqlite3_result_col_iterator_next; - sqlite->result.row.itor.item = tb_database_sqlite3_result_col_iterator_item; - sqlite->result.row.itor.copy = tb_null; - sqlite->result.row.itor.comp = tb_null; - - // init url - if (!tb_url_init(&sqlite->base.url)) break; - - // copy url - tb_url_copy(&sqlite->base.url, url); - - // init state - sqlite->base.state = TB_STATE_OK; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit database - if (sqlite) tb_database_sqlite3_exit((tb_database_sql_impl_t*)sqlite); - sqlite = tb_null; - } - - // ok? - return (tb_database_sql_ref_t)sqlite; -} - diff --git a/core/src/tbox/src/tbox/database/impl/sqlite3.h b/core/src/tbox/src/tbox/database/impl/sqlite3.h deleted file mode 100644 index 871f5d9ef..000000000 --- a/core/src/tbox/src/tbox/database/impl/sqlite3.h +++ /dev/null @@ -1,62 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file sqlite3.h - */ -#ifndef TB_DATABASE_IMPL_SQLITE3_H -#define TB_DATABASE_IMPL_SQLITE3_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* probe sqlite3 from the url - * - * @param url the database url - * - * @return the score - */ -tb_size_t tb_database_sqlite3_probe(tb_url_ref_t url); - -/* init sqlite3 - * - * @param url the database url - * - * @return the database handle - */ -tb_database_sql_ref_t tb_database_sqlite3_init(tb_url_ref_t url); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/database/prefix.h b/core/src/tbox/src/tbox/database/prefix.h deleted file mode 100644 index 6bc82299d..000000000 --- a/core/src/tbox/src/tbox/database/prefix.h +++ /dev/null @@ -1,38 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * @ingroup database - * - */ -#ifndef TB_DATABASE_PREFIX_H -#define TB_DATABASE_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../libc/libc.h" -#include "../network/url.h" -#include "../container/iterator.h" - - -#endif diff --git a/core/src/tbox/src/tbox/database/sql.c b/core/src/tbox/src/tbox/database/sql.c deleted file mode 100644 index c866c0ace..000000000 --- a/core/src/tbox/src/tbox/database/sql.c +++ /dev/null @@ -1,414 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file sql.c - * @defgroup database - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "database" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "sql.h" -#include "impl/prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_database_sql_ref_t tb_database_sql_init(tb_char_t const* url) -{ - // check - tb_assert_and_check_return_val(url, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_database_sql_ref_t database = tb_null; - tb_url_t database_url; - do - { - // trace - tb_trace_d("init: %s: ..", url); - - // init url - if (!tb_url_init(&database_url)) break; - - // make url - if (!tb_url_cstr_set(&database_url, url)) break; - - // check protocol - tb_size_t protocol = tb_url_protocol(&database_url); - tb_assert_and_check_break(protocol == TB_URL_PROTOCOL_SQL || protocol == TB_URL_PROTOCOL_FILE); - - // the probe func - static tb_size_t (*s_probe[])(tb_url_ref_t) = - { - tb_null -#ifdef TB_CONFIG_PACKAGE_HAVE_MYSQL - , tb_database_mysql_probe -#endif -#ifdef TB_CONFIG_PACKAGE_HAVE_SQLITE3 - , tb_database_sqlite3_probe -#endif - }; - - // the init func - static tb_database_sql_ref_t (*s_init[])(tb_url_ref_t) = - { - tb_null -#ifdef TB_CONFIG_PACKAGE_HAVE_MYSQL - , tb_database_mysql_init -#endif -#ifdef TB_CONFIG_PACKAGE_HAVE_SQLITE3 - , tb_database_sqlite3_init -#endif - }; - - // probe the database type - tb_size_t i = 1; - tb_size_t n = tb_arrayn(s_probe); - tb_size_t s = 0; - tb_size_t m = 0; - for (; i < n; i++) - { - if (s_probe[i]) - { - // probe it - tb_size_t score = s_probe[i](&database_url); - if (score > s) - { - // save the max score - s = score; - m = i; - - // ok? - if (score == 100) break; - } - } - } - tb_check_break(m < n && s_init[m]); - - // init it - database = s_init[m](&database_url); - tb_assert_and_check_break(database); - - // trace - tb_trace_d("init: %s: ok", url); - - // ok - ok = tb_true; - - } while (0); - - // exit url - tb_url_exit(&database_url); - - // failed? - if (!ok) - { - // trace - tb_trace_d("init: %s: no", url); - - // exit database - if (database) tb_database_sql_exit(database); - database = tb_null; - } - - // ok? - return database; -} -tb_void_t tb_database_sql_exit(tb_database_sql_ref_t database) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return(impl); - - // trace - tb_trace_d("exit: .."); - - // exit it - if (impl->exit) impl->exit(impl); - - // trace - tb_trace_d("exit: ok"); -} -tb_size_t tb_database_sql_type(tb_database_sql_ref_t database) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl, TB_DATABASE_SQL_TYPE_NONE); - - // the database type - return impl->type; -} -tb_bool_t tb_database_sql_open(tb_database_sql_ref_t database) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl && impl->open, tb_false); - - // opened? - tb_check_return_val(!impl->bopened, tb_true); - - // init state - impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR; - - // open it - impl->bopened = impl->open(impl); - - // save state - if (impl->bopened) impl->state = TB_STATE_OK; - - // ok? - return impl->bopened; -} -tb_void_t tb_database_sql_clos(tb_database_sql_ref_t database) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return(impl); - - // opened? - tb_check_return(impl->bopened); - - // clos it - if (impl->clos) impl->clos(impl); - - // closed - impl->bopened = tb_false; - - // clear state - impl->state = TB_STATE_OK; -} -tb_size_t tb_database_sql_state(tb_database_sql_ref_t database) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl, TB_STATE_UNKNOWN_ERROR); - - // the state - return impl->state; -} -tb_bool_t tb_database_sql_begin(tb_database_sql_ref_t database) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl && impl->commit, tb_false); - - // init state - impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR; - - // opened? - tb_assert_and_check_return_val(impl->bopened, tb_false); - - // begin it - tb_bool_t ok = impl->begin(impl); - - // save state - if (ok) impl->state = TB_STATE_OK; - - // ok? - return ok; -} -tb_bool_t tb_database_sql_commit(tb_database_sql_ref_t database) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl && impl->commit, tb_false); - - // init state - impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR; - - // opened? - tb_assert_and_check_return_val(impl->bopened, tb_false); - - // commit it - tb_bool_t ok = impl->commit(impl); - - // save state - if (ok) impl->state = TB_STATE_OK; - - // ok? - return ok; -} -tb_bool_t tb_database_sql_rollback(tb_database_sql_ref_t database) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl && impl->rollback, tb_false); - - // init state - impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR; - - // opened? - tb_assert_and_check_return_val(impl->bopened, tb_false); - - // rollback it - tb_bool_t ok = impl->rollback(impl); - - // save state - if (ok) impl->state = TB_STATE_OK; - - // ok? - return ok; -} -tb_bool_t tb_database_sql_done(tb_database_sql_ref_t database, tb_char_t const* sql) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl && impl->done && sql, tb_false); - - // init state - impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR; - - // opened? - tb_assert_and_check_return_val(impl->bopened, tb_false); - - // done it - tb_bool_t ok = impl->done(impl, sql); - - // trace - tb_trace_d("done: sql: %s: %s", sql, ok? "ok" : "no"); - - // save state - if (ok) impl->state = TB_STATE_OK; - - // ok? - return ok; -} -tb_iterator_ref_t tb_database_sql_result_load(tb_database_sql_ref_t database, tb_bool_t ball) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl && impl->result_load, tb_null); - - // init state - impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR; - - // opened? - tb_assert_and_check_return_val(impl->bopened, tb_null); - - // load it - tb_iterator_ref_t result = impl->result_load(impl, ball); - - // save state - if (result) impl->state = TB_STATE_OK; - - // ok? - return result; -} -tb_void_t tb_database_sql_result_exit(tb_database_sql_ref_t database, tb_iterator_ref_t result) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return(impl && impl->result_exit && result); - - // opened? - tb_assert_and_check_return(impl->bopened); - - // exit it - impl->result_exit(impl, result); - - // clear state - impl->state = TB_STATE_OK; -} -tb_database_sql_statement_ref_t tb_database_sql_statement_init(tb_database_sql_ref_t database, tb_char_t const* sql) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl && impl->statement_init && sql, tb_null); - - // init state - impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR; - - // opened? - tb_assert_and_check_return_val(impl->bopened, tb_null); - - // init statement - tb_database_sql_statement_ref_t statement = impl->statement_init(impl, sql); - - // save state - if (statement) impl->state = TB_STATE_OK; - - // ok? - return statement; -} -tb_void_t tb_database_sql_statement_exit(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return(impl && impl->statement_done && statement); - - // opened? - tb_assert_and_check_return(impl->bopened); - - // exit statement - impl->statement_exit(impl, statement); - - // clear state - impl->state = TB_STATE_OK; -} -tb_bool_t tb_database_sql_statement_done(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl && impl->statement_done && statement, tb_false); - - // init state - impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR; - - // opened? - tb_assert_and_check_return_val(impl->bopened, tb_false); - - // done statement - tb_bool_t ok = impl->statement_done(impl, statement); - - // save state - if (ok) impl->state = TB_STATE_OK; - - // ok? - return ok; -} -tb_bool_t tb_database_sql_statement_bind(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size) -{ - // check - tb_database_sql_impl_t* impl = (tb_database_sql_impl_t*)database; - tb_assert_and_check_return_val(impl && impl->statement_bind && statement && list && size, tb_false); - - // init state - impl->state = TB_STATE_DATABASE_UNKNOWN_ERROR; - - // opened? - tb_assert_and_check_return_val(impl->bopened, tb_false); - - // bind statement argument - tb_bool_t ok = impl->statement_bind(impl, statement, list, size); - - // save state - if (ok) impl->state = TB_STATE_OK; - - // ok? - return ok; -} diff --git a/core/src/tbox/src/tbox/database/sql.h b/core/src/tbox/src/tbox/database/sql.h deleted file mode 100644 index 62e06facd..000000000 --- a/core/src/tbox/src/tbox/database/sql.h +++ /dev/null @@ -1,339 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file sql.h - * @ingroup database - */ -#ifndef TB_DATABASE_SQL_H -#define TB_DATABASE_SQL_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "value.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the sql database type enum -typedef enum __tb_database_sql_type_e -{ - TB_DATABASE_SQL_TYPE_NONE = 0 -, TB_DATABASE_SQL_TYPE_MYSQL = 1 -, TB_DATABASE_SQL_TYPE_SQLITE3 = 2 - -}tb_database_sql_type_e; - -/// the database sql ref type -typedef __tb_typeref__(database_sql); - -/// the database sql statement ref type -typedef __tb_typeref__(database_sql_statement); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init sql database - * - * @param url the database url - * "sql://localhost/?type=mysql&username=xxxx&password=xxxx" - * "sql://localhost:3306/?type=mysql&username=xxxx&password=xxxx&database=xxxx" - * "sql:///home/file.sqlitedb?type=sqlite3" - * "/home/file.sqlite3" - * "file:///home/file.sqlitedb" - * "C://home/file.sqlite3" - * - * @return the database - */ -tb_database_sql_ref_t tb_database_sql_init(tb_char_t const* url); - -/*! exit database - * - * @param database the database handle - */ -tb_void_t tb_database_sql_exit(tb_database_sql_ref_t database); - -/*! the database type - * - * @param database the database handle - * - * @return the database type - */ -tb_size_t tb_database_sql_type(tb_database_sql_ref_t database); - -/*! open database - * - * @code - tb_database_sql_ref_t database = tb_database_sql_init("sql://localhost/?type=mysql&username=xxxx&password=xxxx"); - if (database) - { - // open it - if (tb_database_sql_open(database)) - { - // done it - // ... - - // close it - tb_database_sql_clos(database); - } - tb_database_sql_exit(database); - } - * @endcode - * - * @param database the database handle - * - * @return tb_true or tb_false - */ -tb_bool_t tb_database_sql_open(tb_database_sql_ref_t database); - -/*! clos database - * - * @param database the database handle - */ -tb_void_t tb_database_sql_clos(tb_database_sql_ref_t database); - -/*! begin transaction - * - * @param database the database handle - * - * @return tb_true or tb_false - */ -tb_bool_t tb_database_sql_begin(tb_database_sql_ref_t database); - -/*! commit transaction - * - * @param database the database handle - * - * @return tb_true or tb_false - */ -tb_bool_t tb_database_sql_commit(tb_database_sql_ref_t database); - -/*! rollback transaction - * - * @param database the database handle - * - * @return tb_true or tb_false - */ -tb_bool_t tb_database_sql_rollback(tb_database_sql_ref_t database); - -/*! the database state - * - * @param database the database handle - * - * @return the database state - */ -tb_size_t tb_database_sql_state(tb_database_sql_ref_t database); - -/*! done database - * - * @code - * - * // done sql - * if (!tb_database_sql_done(database, "select * from table")) - * { - * // trace - * tb_trace_e("done sql failed, error: %s", tb_state_cstr(tb_database_sql_state(database))); - * return ; - * } - * - * // load result - * // .. - * - * @endcode - * - * @param database the database handle - * @param sql the sql command - * - * @return tb_true or tb_false - */ -tb_bool_t tb_database_sql_done(tb_database_sql_ref_t database, tb_char_t const* sql); - -/*! load the database result - * - * @code - * - // done sql - // .. - - // load result - tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_true); - if (result) - { - // walk result - tb_for_all_if (tb_iterator_ref_t, row, result, row) - { - // walk values - tb_for_all_if (tb_database_sql_value_t*, value, row, value) - { - tb_trace_i("name: %s, data: %s, at: %lux%lu", tb_database_sql_value_name(value), tb_database_sql_value_text(value), row_itor, item_itor); - } - } - - // exit result - tb_database_sql_result_exit(result); - } - - // load result - tb_iterator_ref_t result = tb_database_sql_result_load(database, tb_false); - if (result) - { - // walk result - tb_for_all_if (tb_iterator_ref_t, row, result, row) - { - // field count - tb_trace_i("count: %lu", tb_iterator_size(row)); - - // id - tb_database_sql_value_t const* id = tb_iterator_item(row, 0); - if (id) - { - tb_trace_i("id: %d", tb_database_sql_value_int32(id)); - } - - // name - tb_database_sql_value_t const* name = tb_iterator_item(row, 1); - if (name) - { - tb_trace_i("name: %s", tb_database_sql_value_text(name)); - } - - // blob - tb_database_sql_value_t const* blob = tb_iterator_item(row, 2); - if (blob) - { - // data? - tb_stream_ref_t stream = tb_null; - if (tb_database_sql_value_blob(blob)) - { - // trace - tb_trace_i("[data: %p, size: %lu] ", tb_database_sql_value_blob(blob), tb_database_sql_value_size(blob)); - } - // stream? - else if ((stream = tb_database_sql_value_blob_stream(blob))) - { - // trace - tb_trace_i("[stream: %p, size: %lld] ", stream, tb_stream_size(stream)); - - // read stream - // ... - } - // null? - else - { - // trace - tb_trace_i("[%s:null] ", tb_database_sql_value_name(blob)); - } - } - - } - - // exit result - tb_database_sql_result_exit(result); - } - - * @endcode - * - * @param database the database handle - * @param try_all try loading all result into memory - * - * @return the database result - */ -tb_iterator_ref_t tb_database_sql_result_load(tb_database_sql_ref_t database, tb_bool_t try_all); - -/*! exit the database result - * - * @param database the database handle - * @param result the database result - */ -tb_void_t tb_database_sql_result_exit(tb_database_sql_ref_t database, tb_iterator_ref_t result); - -/*! init the database statement - * - * @param database the database handle - * @param sql the sql command - * - * @return the statement handle - */ -tb_database_sql_statement_ref_t tb_database_sql_statement_init(tb_database_sql_ref_t database, tb_char_t const* sql); - -/*! exit the database statement - * - * @param database the database handle - * @param statement the statement handle - */ -tb_void_t tb_database_sql_statement_exit(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement); - -/*! done the database statement - * - * @code - tb_database_sql_statement_ref_t statement = tb_database_sql_statement_init(database, "select * from table where id=?"); - if (statement) - { - // bind arguments - tb_database_sql_value_t list[1] = {0}; - tb_database_sql_value_set_int32(&list[0], 12345); - if (tb_database_sql_statement_bind(database, statement, list, tb_arrayn(list))) - { - // done statement - if (tb_database_sql_statement_done(database, statement)) - { - // load result - // ... - } - } - - // exit statement - tb_database_sql_statement_exit(database, statement); - } - * @endcode - * - * @param database the database handle - * @param statement the statement handle - * - * @return tb_true or tb_false - */ -tb_bool_t tb_database_sql_statement_done(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement); - -/*! bind the database statement argument - * - * @param database the database handle - * @param statement the statement handle - * @param list the argument value list - * @param size the argument value count - * - * @return tb_true or tb_false - */ -tb_bool_t tb_database_sql_statement_bind(tb_database_sql_ref_t database, tb_database_sql_statement_ref_t statement, tb_database_sql_value_t const* list, tb_size_t size); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/database/value.c b/core/src/tbox/src/tbox/database/value.c deleted file mode 100644 index 5909a0588..000000000 --- a/core/src/tbox/src/tbox/database/value.c +++ /dev/null @@ -1,496 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file value.c - * @ingroup database - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "value" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "value.h" -#include "../stream/stream.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_size_t tb_database_sql_value_size(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, 0); - - // done - switch (value->type) - { - case TB_DATABASE_SQL_VALUE_TYPE_TEXT: - if (!value->u.text.hint && value->u.text.data) - { - ((tb_database_sql_value_t*)value)->u.text.hint = tb_strlen(value->u.text.data); - } - return value->u.text.hint; - case TB_DATABASE_SQL_VALUE_TYPE_BLOB32: - case TB_DATABASE_SQL_VALUE_TYPE_BLOB16: - case TB_DATABASE_SQL_VALUE_TYPE_BLOB8: - return value->u.blob.size; - case TB_DATABASE_SQL_VALUE_TYPE_INT32: - case TB_DATABASE_SQL_VALUE_TYPE_UINT32: -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_DATABASE_SQL_VALUE_TYPE_FLOAT: -#endif - return 4; - case TB_DATABASE_SQL_VALUE_TYPE_INT64: - case TB_DATABASE_SQL_VALUE_TYPE_UINT64: -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE: -#endif - return 8; - case TB_DATABASE_SQL_VALUE_TYPE_INT16: - case TB_DATABASE_SQL_VALUE_TYPE_UINT16: - return 2; - case TB_DATABASE_SQL_VALUE_TYPE_INT8: - case TB_DATABASE_SQL_VALUE_TYPE_UINT8: - return 1; - default: - tb_trace_e("unknown type: %lu", value->type); - break; - } - - return 0; -} -tb_int8_t tb_database_sql_value_int8(tb_database_sql_value_t const* value) -{ - return (tb_int8_t)tb_database_sql_value_int32(value); -} -tb_int16_t tb_database_sql_value_int16(tb_database_sql_value_t const* value) -{ - return (tb_int16_t)tb_database_sql_value_int32(value); -} -tb_int32_t tb_database_sql_value_int32(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, 0); - - // done - switch (value->type) - { - case TB_DATABASE_SQL_VALUE_TYPE_INT32: - return (tb_int32_t)value->u.i32; - case TB_DATABASE_SQL_VALUE_TYPE_INT64: - return (tb_int32_t)value->u.i64; - case TB_DATABASE_SQL_VALUE_TYPE_INT16: - return (tb_int32_t)value->u.i16; - case TB_DATABASE_SQL_VALUE_TYPE_INT8: - return (tb_int32_t)value->u.i8; - case TB_DATABASE_SQL_VALUE_TYPE_UINT32: - return (tb_int32_t)value->u.u32; - case TB_DATABASE_SQL_VALUE_TYPE_UINT64: - return (tb_int32_t)value->u.u64; - case TB_DATABASE_SQL_VALUE_TYPE_UINT16: - return (tb_int32_t)value->u.u16; - case TB_DATABASE_SQL_VALUE_TYPE_UINT8: - return (tb_int32_t)value->u.u8; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_DATABASE_SQL_VALUE_TYPE_FLOAT: - return (tb_int32_t)value->u.f; - case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE: - return (tb_int32_t)value->u.d; -#endif - case TB_DATABASE_SQL_VALUE_TYPE_TEXT: - return value->u.text.data? (tb_int32_t)tb_stoi32(value->u.text.data) : 0; - default: - tb_trace_e("unknown number type: %lu", value->type); - break; - } - - return 0; -} -tb_int64_t tb_database_sql_value_int64(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, 0); - - // done - switch (value->type) - { - case TB_DATABASE_SQL_VALUE_TYPE_INT64: - return (tb_int64_t)value->u.i64; - case TB_DATABASE_SQL_VALUE_TYPE_INT32: - return (tb_int64_t)value->u.i32; - case TB_DATABASE_SQL_VALUE_TYPE_INT16: - return (tb_int64_t)value->u.i16; - case TB_DATABASE_SQL_VALUE_TYPE_INT8: - return (tb_int64_t)value->u.i8; - case TB_DATABASE_SQL_VALUE_TYPE_UINT64: - return (tb_int64_t)value->u.u64; - case TB_DATABASE_SQL_VALUE_TYPE_UINT32: - return (tb_int64_t)value->u.u32; - case TB_DATABASE_SQL_VALUE_TYPE_UINT16: - return (tb_int64_t)value->u.u16; - case TB_DATABASE_SQL_VALUE_TYPE_UINT8: - return (tb_int64_t)value->u.u8; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_DATABASE_SQL_VALUE_TYPE_FLOAT: - return (tb_int64_t)value->u.f; - case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE: - return (tb_int64_t)value->u.d; -#endif - case TB_DATABASE_SQL_VALUE_TYPE_TEXT: - return value->u.text.data? (tb_int64_t)tb_stoi64(value->u.text.data) : 0; - default: - tb_trace_e("unknown number type: %lu", value->type); - break; - } - - return 0; -} -tb_uint8_t tb_database_sql_value_uint8(tb_database_sql_value_t const* value) -{ - return (tb_uint8_t)tb_database_sql_value_uint32(value); -} -tb_uint16_t tb_database_sql_value_uint16(tb_database_sql_value_t const* value) -{ - return (tb_uint16_t)tb_database_sql_value_uint32(value); -} -tb_uint32_t tb_database_sql_value_uint32(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, 0); - - // done - switch (value->type) - { - case TB_DATABASE_SQL_VALUE_TYPE_UINT32: - return (tb_uint32_t)value->u.u32; - case TB_DATABASE_SQL_VALUE_TYPE_UINT64: - return (tb_uint32_t)value->u.u64; - case TB_DATABASE_SQL_VALUE_TYPE_UINT16: - return (tb_uint32_t)value->u.u16; - case TB_DATABASE_SQL_VALUE_TYPE_UINT8: - return (tb_uint32_t)value->u.u8; - case TB_DATABASE_SQL_VALUE_TYPE_INT32: - return (tb_uint32_t)value->u.i32; - case TB_DATABASE_SQL_VALUE_TYPE_INT64: - return (tb_uint32_t)value->u.i64; - case TB_DATABASE_SQL_VALUE_TYPE_INT16: - return (tb_uint32_t)value->u.i16; - case TB_DATABASE_SQL_VALUE_TYPE_INT8: - return (tb_uint32_t)value->u.i8; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_DATABASE_SQL_VALUE_TYPE_FLOAT: - return (tb_uint32_t)value->u.f; - case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE: - return (tb_uint32_t)value->u.d; -#endif - case TB_DATABASE_SQL_VALUE_TYPE_TEXT: - return value->u.text.data? (tb_uint32_t)tb_stoi32(value->u.text.data) : 0; - default: - tb_trace_e("unknown number type: %lu", value->type); - break; - } - - return 0; -} -tb_uint64_t tb_database_sql_value_uint64(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, 0); - - // done - switch (value->type) - { - case TB_DATABASE_SQL_VALUE_TYPE_UINT64: - return (tb_uint64_t)value->u.u64; - case TB_DATABASE_SQL_VALUE_TYPE_UINT32: - return (tb_uint64_t)value->u.u32; - case TB_DATABASE_SQL_VALUE_TYPE_UINT16: - return (tb_uint64_t)value->u.u16; - case TB_DATABASE_SQL_VALUE_TYPE_UINT8: - return (tb_uint64_t)value->u.u8; - case TB_DATABASE_SQL_VALUE_TYPE_INT64: - return (tb_uint64_t)value->u.i64; - case TB_DATABASE_SQL_VALUE_TYPE_INT32: - return (tb_uint64_t)value->u.i32; - case TB_DATABASE_SQL_VALUE_TYPE_INT16: - return (tb_uint64_t)value->u.i16; - case TB_DATABASE_SQL_VALUE_TYPE_INT8: - return (tb_uint64_t)value->u.i8; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_DATABASE_SQL_VALUE_TYPE_FLOAT: - return (tb_uint64_t)value->u.f; - case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE: - return (tb_uint64_t)value->u.d; -#endif - case TB_DATABASE_SQL_VALUE_TYPE_TEXT: - return value->u.text.data? (tb_uint64_t)tb_stou64(value->u.text.data) : 0; - default: - tb_trace_e("unknown number type: %lu", value->type); - break; - } - - return 0; -} -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -tb_float_t tb_database_sql_value_float(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, 0); - - // done - switch (value->type) - { - case TB_DATABASE_SQL_VALUE_TYPE_FLOAT: - return value->u.f; - case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE: - return (tb_float_t)value->u.d; - case TB_DATABASE_SQL_VALUE_TYPE_INT64: - return (tb_float_t)value->u.i64; - case TB_DATABASE_SQL_VALUE_TYPE_INT32: - return (tb_float_t)value->u.i32; - case TB_DATABASE_SQL_VALUE_TYPE_INT16: - return (tb_float_t)value->u.i16; - case TB_DATABASE_SQL_VALUE_TYPE_INT8: - return (tb_float_t)value->u.i8; - case TB_DATABASE_SQL_VALUE_TYPE_UINT64: - return (tb_float_t)value->u.u64; - case TB_DATABASE_SQL_VALUE_TYPE_UINT32: - return (tb_float_t)value->u.u32; - case TB_DATABASE_SQL_VALUE_TYPE_UINT16: - return (tb_float_t)value->u.u16; - case TB_DATABASE_SQL_VALUE_TYPE_UINT8: - return (tb_float_t)value->u.u8; - case TB_DATABASE_SQL_VALUE_TYPE_TEXT: - return value->u.text.data? tb_stof(value->u.text.data) : 0; - default: - tb_trace_e("unknown number type: %lu", value->type); - break; - } - - return 0; -} -tb_double_t tb_database_sql_value_double(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, 0); - - // done - switch (value->type) - { - case TB_DATABASE_SQL_VALUE_TYPE_FLOAT: - return (tb_double_t)value->u.f; - case TB_DATABASE_SQL_VALUE_TYPE_DOUBLE: - return value->u.d; - case TB_DATABASE_SQL_VALUE_TYPE_INT64: - return (tb_double_t)value->u.i64; - case TB_DATABASE_SQL_VALUE_TYPE_INT32: - return (tb_double_t)value->u.i32; - case TB_DATABASE_SQL_VALUE_TYPE_INT16: - return (tb_double_t)value->u.i16; - case TB_DATABASE_SQL_VALUE_TYPE_INT8: - return (tb_double_t)value->u.i8; - case TB_DATABASE_SQL_VALUE_TYPE_UINT64: - return (tb_double_t)value->u.u64; - case TB_DATABASE_SQL_VALUE_TYPE_UINT32: - return (tb_double_t)value->u.u32; - case TB_DATABASE_SQL_VALUE_TYPE_UINT16: - return (tb_double_t)value->u.u16; - case TB_DATABASE_SQL_VALUE_TYPE_UINT8: - return (tb_double_t)value->u.u8; - case TB_DATABASE_SQL_VALUE_TYPE_TEXT: - return value->u.text.data? tb_stod(value->u.text.data) : 0; - default: - tb_trace_e("unknown number type: %lu", value->type); - break; - } - - return 0; -} -#endif -tb_void_t tb_database_sql_value_set_null(tb_database_sql_value_t* value) -{ - // check - tb_assert_and_check_return(value); - - // init null - value->type = TB_DATABASE_SQL_VALUE_TYPE_NULL; -} -tb_void_t tb_database_sql_value_set_int8(tb_database_sql_value_t* value, tb_int8_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_INT8; - value->u.i8 = number; -} -tb_void_t tb_database_sql_value_set_int16(tb_database_sql_value_t* value, tb_int16_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_INT16; - value->u.i16 = number; -} -tb_void_t tb_database_sql_value_set_int32(tb_database_sql_value_t* value, tb_int32_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_INT32; - value->u.i32 = number; -} -tb_void_t tb_database_sql_value_set_int64(tb_database_sql_value_t* value, tb_int64_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_INT64; - value->u.i64 = number; -} -tb_void_t tb_database_sql_value_set_uint8(tb_database_sql_value_t* value, tb_uint8_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_INT8; - value->u.u8 = number; -} -tb_void_t tb_database_sql_value_set_uint16(tb_database_sql_value_t* value, tb_uint16_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_INT16; - value->u.u16 = number; -} -tb_void_t tb_database_sql_value_set_uint32(tb_database_sql_value_t* value, tb_uint32_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_INT32; - value->u.u32 = number; -} -tb_void_t tb_database_sql_value_set_uint64(tb_database_sql_value_t* value, tb_uint64_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_INT64; - value->u.u64 = number; -} -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -tb_void_t tb_database_sql_value_set_float(tb_database_sql_value_t* value, tb_float_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_FLOAT; - value->u.f = number; -} -tb_void_t tb_database_sql_value_set_double(tb_database_sql_value_t* value, tb_double_t number) -{ - // check - tb_assert_and_check_return(value); - - // init number - value->type = TB_DATABASE_SQL_VALUE_TYPE_DOUBLE; - value->u.d = number; -} -#endif -tb_void_t tb_database_sql_value_set_text(tb_database_sql_value_t* value, tb_char_t const* text, tb_size_t hint) -{ - // check - tb_assert_and_check_return(value); - - // init text - value->type = TB_DATABASE_SQL_VALUE_TYPE_TEXT; - value->u.text.data = text; - value->u.text.hint = hint; -} -tb_void_t tb_database_sql_value_set_blob8(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size) -{ - // check - tb_assert_and_check_return(value); - - // init blob - value->type = TB_DATABASE_SQL_VALUE_TYPE_BLOB8; - value->u.blob.data = data; - value->u.blob.size = size; - value->u.blob.stream = tb_null; - - // check size - tb_assert(tb_database_sql_value_size(value) <= TB_MAXU8); -} -tb_void_t tb_database_sql_value_set_blob16(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size) -{ - // check - tb_assert_and_check_return(value); - - // init blob - value->type = TB_DATABASE_SQL_VALUE_TYPE_BLOB16; - value->u.blob.data = data; - value->u.blob.size = size; - value->u.blob.stream = tb_null; - - // check size - tb_assert(tb_database_sql_value_size(value) <= TB_MAXU16); -} -tb_void_t tb_database_sql_value_set_blob32(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size, tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return(value); - - // check stream - tb_hong_t stream_size = 0; - if (stream) - { - // must be opened - tb_assert_and_check_return(tb_stream_is_opened(stream)); - - // the stream size - stream_size = tb_stream_size(stream); - tb_assert_and_check_return(stream_size >= 0 && stream_size < TB_MAXS32); - } - - // init blob - value->type = TB_DATABASE_SQL_VALUE_TYPE_BLOB32; - value->u.blob.data = data; - value->u.blob.size = data? size : (tb_size_t)stream_size; - value->u.blob.stream = stream; - - // check size - tb_assert(tb_database_sql_value_size(value) <= TB_MAXU32); -} diff --git a/core/src/tbox/src/tbox/database/value.h b/core/src/tbox/src/tbox/database/value.h deleted file mode 100644 index 9c41e65ad..000000000 --- a/core/src/tbox/src/tbox/database/value.h +++ /dev/null @@ -1,463 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file value.h - * @ingroup database - * - */ -#ifndef TB_DATABASE_SQL_VALUE_H -#define TB_DATABASE_SQL_VALUE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "../stream/stream.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the sql database value type enum -typedef enum __tb_database_sql_value_type_e -{ - TB_DATABASE_SQL_VALUE_TYPE_NULL = 0 -, TB_DATABASE_SQL_VALUE_TYPE_INT8 = 1 -, TB_DATABASE_SQL_VALUE_TYPE_INT16 = 2 -, TB_DATABASE_SQL_VALUE_TYPE_INT32 = 3 -, TB_DATABASE_SQL_VALUE_TYPE_INT64 = 4 -, TB_DATABASE_SQL_VALUE_TYPE_UINT8 = 5 -, TB_DATABASE_SQL_VALUE_TYPE_UINT16 = 6 -, TB_DATABASE_SQL_VALUE_TYPE_UINT32 = 7 -, TB_DATABASE_SQL_VALUE_TYPE_UINT64 = 8 -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -, TB_DATABASE_SQL_VALUE_TYPE_FLOAT = 13 -, TB_DATABASE_SQL_VALUE_TYPE_DOUBLE = 14 -#endif -, TB_DATABASE_SQL_VALUE_TYPE_BLOB8 = 9 -, TB_DATABASE_SQL_VALUE_TYPE_BLOB16 = 10 -, TB_DATABASE_SQL_VALUE_TYPE_BLOB32 = 11 -, TB_DATABASE_SQL_VALUE_TYPE_TEXT = 12 - -}tb_database_sql_value_type_e; - -/// the sql database value type -typedef struct __tb_database_sql_value_t -{ - /// the type - tb_size_t type; - - /// the name - tb_char_t const* name; - - /// the data - union - { - // int - tb_int8_t i8; - tb_int16_t i16; - tb_int32_t i32; - tb_int64_t i64; - - // uint - tb_uint8_t u8; - tb_uint16_t u16; - tb_uint32_t u32; - tb_uint64_t u64; - - // float -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - tb_float_t f; - tb_double_t d; -#endif - - // blob - struct - { - tb_byte_t const* data; - tb_size_t size; - - // the stream for blob32 - tb_stream_ref_t stream; - - } blob; - - // text - struct - { - tb_char_t const* data; - tb_size_t hint; - - } text; - - }u; - -}tb_database_sql_value_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the value data size - * - * @param value the value - * - * @return the value data size - */ -tb_size_t tb_database_sql_value_size(tb_database_sql_value_t const* value); - -/*! the int8 value - * - * @param value the value - * - * @return the int8 value - */ -tb_int8_t tb_database_sql_value_int8(tb_database_sql_value_t const* value); - -/*! the int16 value - * - * @param value the value - * - * @return the int16 value - */ -tb_int16_t tb_database_sql_value_int16(tb_database_sql_value_t const* value); - -/*! the int32 value - * - * @param value the value - * - * @return the int32 value - */ -tb_int32_t tb_database_sql_value_int32(tb_database_sql_value_t const* value); - -/*! the int64 value - * - * @param value the value - * - * @return the int64 value - */ -tb_int64_t tb_database_sql_value_int64(tb_database_sql_value_t const* value); - -/*! the uint8 value - * - * @param value the value - * - * @return the uint8 value - */ -tb_uint8_t tb_database_sql_value_uint8(tb_database_sql_value_t const* value); - -/*! the uint16 value - * - * @param value the value - * - * @return the uint16 value - */ -tb_uint16_t tb_database_sql_value_uint16(tb_database_sql_value_t const* value); - -/*! the uint32 value - * - * @param value the value - * - * @return the uint32 value - */ -tb_uint32_t tb_database_sql_value_uint32(tb_database_sql_value_t const* value); - -/*! the uint64 value - * - * @param value the value - * - * @return the uint64 value - */ -tb_uint64_t tb_database_sql_value_uint64(tb_database_sql_value_t const* value); - -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -/*! the float value - * - * @param value the value - * - * @return the float value - */ -tb_float_t tb_database_sql_value_float(tb_database_sql_value_t const* value); - -/*! the double value - * - * @param value the value - * - * @return the double value - */ -tb_double_t tb_database_sql_value_double(tb_database_sql_value_t const* value); -#endif - -/*! set the null value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_null(tb_database_sql_value_t* value); - -/*! set the int8 value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_int8(tb_database_sql_value_t* value, tb_int8_t number); - -/*! set the int16 value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_int16(tb_database_sql_value_t* value, tb_int16_t number); - -/*! set the int32 value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_int32(tb_database_sql_value_t* value, tb_int32_t number); - -/*! set the int64 value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_int64(tb_database_sql_value_t* value, tb_int64_t number); - -/*! set the uint8 value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_uint8(tb_database_sql_value_t* value, tb_uint8_t number); - -/*! set the uint16 value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_uint16(tb_database_sql_value_t* value, tb_uint16_t number); - -/*! set the uint32 value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_uint32(tb_database_sql_value_t* value, tb_uint32_t number); - -/*! set the uint64 value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_uint64(tb_database_sql_value_t* value, tb_uint64_t number); - -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -/*! set the float value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_float(tb_database_sql_value_t* value, tb_float_t number); - -/*! set the double value - * - * @param value the value - * @param number the number - */ -tb_void_t tb_database_sql_value_set_double(tb_database_sql_value_t* value, tb_double_t number); -#endif - -/*! set the text value - * - * @param value the value - * @param text the text data - * @param hint the text size hint - */ -tb_void_t tb_database_sql_value_set_text(tb_database_sql_value_t* value, tb_char_t const* text, tb_size_t hint); - -/*! set the blob8 value - * - * @param value the value - * @param data the blob data - * @param size the blob size - */ -tb_void_t tb_database_sql_value_set_blob8(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size); - -/*! set the blob16 value - * - * @param value the value - * @param data the blob data - * @param size the blob size - */ -tb_void_t tb_database_sql_value_set_blob16(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size); - -/*! set the blob32 value - * - * @param value the value - * @param data the blob data - * @param size the blob size - * @param stream the stream, using it if data == null - */ -tb_void_t tb_database_sql_value_set_blob32(tb_database_sql_value_t* value, tb_byte_t const* data, tb_size_t size, tb_stream_ref_t stream); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * inlines - */ - -/// the value is null? -static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_null(tb_database_sql_value_t const* value) -{ - return (value && value->type == TB_DATABASE_SQL_VALUE_TYPE_NULL)? tb_true : tb_false; -} - -/// the value is text? -static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_text(tb_database_sql_value_t const* value) -{ - return (value && value->type == TB_DATABASE_SQL_VALUE_TYPE_TEXT)? tb_true : tb_false; -} - -/// the value is blob? -static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_blob(tb_database_sql_value_t const* value) -{ - return ( value - && ( value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB32 - || value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB16 - || value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB8))? tb_true : tb_false; -} - -/// the value is blob32? -static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_blob32(tb_database_sql_value_t const* value) -{ - return (value && value->type == TB_DATABASE_SQL_VALUE_TYPE_BLOB32)? tb_true : tb_false; -} -/// the value is integer? -static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_integer(tb_database_sql_value_t const* value) -{ - return (value && value->type >= TB_DATABASE_SQL_VALUE_TYPE_INT8 && value->type <= TB_DATABASE_SQL_VALUE_TYPE_UINT64)? tb_true : tb_false; -} - -/// the value is float? -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_float(tb_database_sql_value_t const* value) -{ - return ( value - && ( value->type == TB_DATABASE_SQL_VALUE_TYPE_FLOAT - || value->type == TB_DATABASE_SQL_VALUE_TYPE_DOUBLE))? tb_true : tb_false; -} -#endif - -/// the value is number? -static __tb_inline_force__ tb_bool_t tb_database_sql_value_is_number(tb_database_sql_value_t const* value) -{ - return (value && value->type >= TB_DATABASE_SQL_VALUE_TYPE_INT8 && value->type < TB_DATABASE_SQL_VALUE_TYPE_BLOB8)? tb_true : tb_false; -} - -/// the value type -static __tb_inline_force__ tb_size_t tb_database_sql_value_type(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, TB_DATABASE_SQL_VALUE_TYPE_NULL); - - // the type - return value->type; -} - -/// the value name -static __tb_inline_force__ tb_char_t const* tb_database_sql_value_name(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, tb_null); - - // the name - return value->name; -} - -/// the value text data -static __tb_inline_force__ tb_char_t const* tb_database_sql_value_text(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, tb_null); - - // is text? - if (tb_database_sql_value_is_text(value)) - return value->u.text.data; - // is blob? - else if (tb_database_sql_value_is_blob(value)) - return (tb_char_t const*)value->u.blob.data; - // is null? - else if (tb_database_sql_value_is_null(value)) - return tb_null; - - // trace - tb_trace_e("not text value type: %lu", value->type); - return tb_null; -} - -/// the value blob data -static __tb_inline_force__ tb_byte_t const* tb_database_sql_value_blob(tb_database_sql_value_t const* value) -{ - // check - tb_assert_and_check_return_val(value, tb_null); - - // is blob? - if (tb_database_sql_value_is_blob(value)) - return value->u.blob.data; - // is text? - else if (tb_database_sql_value_is_text(value)) - return (tb_byte_t const*)value->u.text.data; - // is null? - else if (tb_database_sql_value_is_null(value)) - return tb_null; - - // trace - tb_trace_e("not blob value type: %lu", value->type); - return tb_null; -} - -/// the value blob stream -static __tb_inline_force__ tb_stream_ref_t tb_database_sql_value_blob_stream(tb_database_sql_value_t const* value) -{ - // the blob stream - return tb_database_sql_value_is_blob(value)? value->u.blob.stream : tb_null; -} - -/// set the value name -static __tb_inline_force__ tb_void_t tb_database_sql_value_name_set(tb_database_sql_value_t* value, tb_char_t const* name) -{ - // check - tb_assert_and_check_return(value); - - // set the name - value->name = name; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - - -#endif diff --git a/core/src/tbox/src/tbox/object/array.c b/core/src/tbox/src/tbox/object/array.c deleted file mode 100644 index f484a5761..000000000 --- a/core/src/tbox/src/tbox/object/array.c +++ /dev/null @@ -1,266 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file array.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_array" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" -#include "../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the array type -typedef struct __tb_oc_array_t -{ - // the object base - tb_object_t base; - - // the vector - tb_vector_ref_t vector; - - // is increase refn? - tb_bool_t incr; - -}tb_oc_array_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_oc_array_t* tb_oc_array_cast(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_ARRAY, tb_null); - - // cast - return (tb_oc_array_t*)object; -} -static tb_object_ref_t tb_oc_array_copy(tb_object_ref_t object) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return_val(array && array->vector, tb_null); - - // init copy - tb_oc_array_t* copy = (tb_oc_array_t*)tb_oc_array_init(tb_vector_grow(array->vector), array->incr); - tb_assert_and_check_return_val(copy && copy->vector, tb_null); - - // refn++ - tb_for_all (tb_object_ref_t, item, array->vector) - { - if (item) tb_object_retain(item); - } - - // copy - tb_vector_copy(copy->vector, array->vector); - - // ok - return (tb_object_ref_t)copy; -} -static tb_void_t tb_oc_array_exit(tb_object_ref_t object) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return(array); - - // exit vector - if (array->vector) tb_vector_exit(array->vector); - array->vector = tb_null; - - // exit it - tb_free(array); -} -static tb_void_t tb_oc_array_clear(tb_object_ref_t object) -{ - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return(array && array->vector); - - // clear vector - tb_vector_clear(array->vector); -} -static tb_oc_array_t* tb_oc_array_init_base() -{ - // done - tb_bool_t ok = tb_false; - tb_oc_array_t* array = tb_null; - do - { - // make array - array = tb_malloc0_type(tb_oc_array_t); - tb_assert_and_check_break(array); - - // init array - if (!tb_object_init((tb_object_ref_t)array, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_ARRAY)) break; - - // init base - array->base.copy = tb_oc_array_copy; - array->base.exit = tb_oc_array_exit; - array->base.clear = tb_oc_array_clear; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (array) tb_object_exit((tb_object_ref_t)array); - array = tb_null; - } - - // ok? - return array; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_object_ref_t tb_oc_array_init(tb_size_t grow, tb_bool_t incr) -{ - // done - tb_bool_t ok = tb_false; - tb_oc_array_t* array = tb_null; - do - { - // make array - array = tb_oc_array_init_base(); - tb_assert_and_check_break(array); - - // init element - tb_element_t element = tb_element_obj(); - - // init vector - array->vector = tb_vector_init(grow, element); - tb_assert_and_check_break(array->vector); - - // init incr - array->incr = incr; - - // ok - ok = tb_true; - - } while (0); - - // failed - if (!ok) - { - // exit it - if (array) tb_oc_array_exit((tb_object_ref_t)array); - array = tb_null; - } - - // ok? - return (tb_object_ref_t)array; -} -tb_size_t tb_oc_array_size(tb_object_ref_t object) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return_val(array && array->vector, 0); - - // size - return tb_vector_size(array->vector); -} -tb_object_ref_t tb_oc_array_item(tb_object_ref_t object, tb_size_t index) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return_val(array && array->vector, tb_null); - - // item - return (tb_object_ref_t)tb_iterator_item(array->vector, index); -} -tb_iterator_ref_t tb_oc_array_itor(tb_object_ref_t object) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return_val(array, tb_null); - - // iterator - return (tb_iterator_ref_t)array->vector; -} -tb_void_t tb_oc_array_remove(tb_object_ref_t object, tb_size_t index) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return(array && array->vector); - - // remove - tb_vector_remove(array->vector, index); -} -tb_void_t tb_oc_array_append(tb_object_ref_t object, tb_object_ref_t item) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return(array && array->vector && item); - - // insert - tb_vector_insert_tail(array->vector, item); - - // refn-- - if (!array->incr) tb_object_exit(item); -} -tb_void_t tb_oc_array_insert(tb_object_ref_t object, tb_size_t index, tb_object_ref_t item) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return(array && array->vector && item); - - // insert - tb_vector_insert_prev(array->vector, index, item); - - // refn-- - if (!array->incr) tb_object_exit(item); -} -tb_void_t tb_oc_array_replace(tb_object_ref_t object, tb_size_t index, tb_object_ref_t item) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return(array && array->vector && item); - - // replace - tb_vector_replace(array->vector, index, item); - - // refn-- - if (!array->incr) tb_object_exit(item); -} -tb_void_t tb_oc_array_incr(tb_object_ref_t object, tb_bool_t incr) -{ - // check - tb_oc_array_t* array = tb_oc_array_cast(object); - tb_assert_and_check_return(array); - - array->incr = incr; -} diff --git a/core/src/tbox/src/tbox/object/array.h b/core/src/tbox/src/tbox/object/array.h deleted file mode 100644 index cfac90d82..000000000 --- a/core/src/tbox/src/tbox/object/array.h +++ /dev/null @@ -1,130 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file array.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_ARRAY_H -#define TB_OBJECT_ARRAY_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init array - * - * @param grow the array grow - * @param incr is increase refn? - * - * @return the array object - */ -tb_object_ref_t tb_oc_array_init(tb_size_t grow, tb_bool_t incr); - -/*! the array size - * - * @param array the array object - * - * @return the array size - */ -tb_size_t tb_oc_array_size(tb_object_ref_t array); - -/*! the array item at index - * - * @param array the array object - * @param index the array index - * - * @return the array item - */ -tb_object_ref_t tb_oc_array_item(tb_object_ref_t array, tb_size_t index); - -/*! set the array incr - * - * @param array the array object - * @param incr is increase refn? - */ -tb_void_t tb_oc_array_incr(tb_object_ref_t array, tb_bool_t incr); - -/*! the array iterator - * - * @param array the array object - * - * @return the array iterator - * - * @code - * tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(array)) - * { - * if (item) - * { - * // ... - * } - * } - * @endcode - */ -tb_iterator_ref_t tb_oc_array_itor(tb_object_ref_t array); - -/*! remove the item from index - * - * @param array the array object - * @param index the array index - */ -tb_void_t tb_oc_array_remove(tb_object_ref_t array, tb_size_t index); - -/*! append item to array - * - * @param array the array object - * @param index the array index - */ -tb_void_t tb_oc_array_append(tb_object_ref_t array, tb_object_ref_t item); - -/*! insert item to array - * - * @param array the array object - * @param index the array index - * @param item the array item - */ -tb_void_t tb_oc_array_insert(tb_object_ref_t array, tb_size_t index, tb_object_ref_t item); - -/*! replace item to array - * - * @param array the array object - * @param index the array index - * @param item the array item - */ -tb_void_t tb_oc_array_replace(tb_object_ref_t array, tb_size_t index, tb_object_ref_t item); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/boolean.c b/core/src/tbox/src/tbox/object/boolean.c deleted file mode 100644 index 4e32ec5c2..000000000 --- a/core/src/tbox/src/tbox/object/boolean.c +++ /dev/null @@ -1,133 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file boolean.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_boolean" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the boolean type -typedef struct __tb_oc_boolean_t -{ - // the object base - tb_object_t base; - - // the boolean value - tb_bool_t value; - -}tb_oc_boolean_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_oc_boolean_t* tb_oc_boolean_cast(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_BOOLEAN, tb_null); - - // cast - return (tb_oc_boolean_t*)object; -} - -static tb_object_ref_t tb_oc_boolean_copy(tb_object_ref_t object) -{ - // check - tb_oc_boolean_t* boolean = (tb_oc_boolean_t*)object; - tb_assert_and_check_return_val(boolean, tb_null); - - // copy - return object; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * globals - */ - -// true -static tb_oc_boolean_t const g_boolean_true = -{ - { - TB_OBJECT_FLAG_READONLY | TB_OBJECT_FLAG_SINGLETON - , TB_OBJECT_TYPE_BOOLEAN - , 1 - , tb_null - , tb_oc_boolean_copy - , tb_null - , tb_null - } -, tb_true - -}; - -// false -static tb_oc_boolean_t const g_boolean_false = -{ - { - TB_OBJECT_FLAG_READONLY | TB_OBJECT_FLAG_SINGLETON - , TB_OBJECT_TYPE_BOOLEAN - , 1 - , tb_null - , tb_oc_boolean_copy - , tb_null - , tb_null - } -, tb_false - -}; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_object_ref_t tb_oc_boolean_init(tb_bool_t value) -{ - return value? tb_oc_boolean_true() : tb_oc_boolean_false(); -} -tb_object_ref_t tb_oc_boolean_true() -{ - return (tb_object_ref_t)&g_boolean_true; -} -tb_object_ref_t tb_oc_boolean_false() -{ - return (tb_object_ref_t)&g_boolean_false; -} -tb_bool_t tb_oc_boolean_bool(tb_object_ref_t object) -{ - tb_oc_boolean_t* boolean = tb_oc_boolean_cast(object); - tb_assert_and_check_return_val(boolean, tb_false); - - return boolean->value; -} - diff --git a/core/src/tbox/src/tbox/object/boolean.h b/core/src/tbox/src/tbox/object/boolean.h deleted file mode 100644 index 6926edb56..000000000 --- a/core/src/tbox/src/tbox/object/boolean.h +++ /dev/null @@ -1,78 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file boolean.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_BOOLEAN_H -#define TB_OBJECT_BOOLEAN_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init boolean - * - * @param value the value - * - * @return the boolean object - */ -tb_object_ref_t tb_oc_boolean_init(tb_bool_t value); - -/*! the boolean value: true - * - * @return the boolean object - */ -tb_object_ref_t tb_oc_boolean_true(tb_noarg_t); - -/*! the boolean value: false - * - * @return the boolean object - */ -tb_object_ref_t tb_oc_boolean_false(tb_noarg_t); - -/*! the boolean value - * - * @param the boolean object - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_boolean_bool(tb_object_ref_t boolean); - - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/data.c b/core/src/tbox/src/tbox/object/data.c deleted file mode 100644 index c152d241e..000000000 --- a/core/src/tbox/src/tbox/object/data.c +++ /dev/null @@ -1,258 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file data.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_data" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" -#include "../utils/utils.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the data type -typedef struct __tb_oc_data_t -{ - // the object base - tb_object_t base; - - // the data buffer - tb_buffer_t buffer; - -}tb_oc_data_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_oc_data_t* tb_oc_data_cast(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_DATA, tb_null); - - // cast - return (tb_oc_data_t*)object; -} -static tb_object_ref_t tb_oc_data_copy(tb_object_ref_t object) -{ - return tb_oc_data_init_from_data(tb_oc_data_getp(object), tb_oc_data_size(object)); -} -static tb_void_t tb_oc_data_exit(tb_object_ref_t object) -{ - tb_oc_data_t* data = tb_oc_data_cast(object); - if (data) - { - tb_buffer_exit(&data->buffer); - tb_free(data); - } -} -static tb_void_t tb_oc_data_clear(tb_object_ref_t object) -{ - tb_oc_data_t* data = tb_oc_data_cast(object); - if (data) tb_buffer_clear(&data->buffer); -} -static tb_oc_data_t* tb_oc_data_init_base() -{ - // done - tb_bool_t ok = tb_false; - tb_oc_data_t* data = tb_null; - do - { - // make data - data = tb_malloc0_type(tb_oc_data_t); - tb_assert_and_check_break(data); - - // init data - if (!tb_object_init((tb_object_ref_t)data, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_DATA)) break; - - // init base - data->base.copy = tb_oc_data_copy; - data->base.exit = tb_oc_data_exit; - data->base.clear = tb_oc_data_clear; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (data) tb_object_exit((tb_object_ref_t)data); - data = tb_null; - } - - // ok? - return data; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_object_ref_t tb_oc_data_init_from_url(tb_char_t const* url) -{ - // check - tb_assert_and_check_return_val(url, tb_null); - - // init stream - tb_stream_ref_t stream = tb_stream_init_from_url(url); - tb_assert_and_check_return_val(stream, tb_null); - - // make stream - tb_object_ref_t object = tb_null; - if (tb_stream_open(stream)) - { - // read all data - tb_size_t size = 0; - tb_byte_t* data = (tb_byte_t*)tb_stream_bread_all(stream, tb_false, &size); - if (data) - { - // make object - object = tb_oc_data_init_from_data(data, size); - - // exit data - tb_free(data); - } - - // exit stream - tb_stream_exit(stream); - } - - // ok? - return object; -} -tb_object_ref_t tb_oc_data_init_from_data(tb_pointer_t addr, tb_size_t size) -{ - // make - tb_oc_data_t* data = tb_oc_data_init_base(); - tb_assert_and_check_return_val(data, tb_null); - - // init buffer - if (!tb_buffer_init(&data->buffer)) - { - tb_oc_data_exit((tb_object_ref_t)data); - return tb_null; - } - - // copy data - if (addr && size) tb_buffer_memncpy(&data->buffer, (tb_byte_t const*)addr, size); - - // ok - return (tb_object_ref_t)data; -} -tb_object_ref_t tb_oc_data_init_from_buffer(tb_buffer_ref_t pbuf) -{ - // make - tb_oc_data_t* data = tb_oc_data_init_base(); - tb_assert_and_check_return_val(data, tb_null); - - // init buffer - if (!tb_buffer_init(&data->buffer)) - { - tb_oc_data_exit((tb_object_ref_t)data); - return tb_null; - } - - // copy data - if (pbuf) tb_buffer_memcpy(&data->buffer, pbuf); - - // ok - return (tb_object_ref_t)data; -} -tb_pointer_t tb_oc_data_getp(tb_object_ref_t object) -{ - // check - tb_oc_data_t* data = tb_oc_data_cast(object); - tb_assert_and_check_return_val(data, tb_null); - - // data - return tb_buffer_data(&data->buffer); -} -tb_bool_t tb_oc_data_setp(tb_object_ref_t object, tb_pointer_t addr, tb_size_t size) -{ - // check - tb_oc_data_t* data = tb_oc_data_cast(object); - tb_assert_and_check_return_val(data && addr, tb_false); - - // data - tb_buffer_memncpy(&data->buffer, (tb_byte_t const*)addr, size); - - // ok - return tb_true; -} -tb_size_t tb_oc_data_size(tb_object_ref_t object) -{ - // check - tb_oc_data_t* data = tb_oc_data_cast(object); - tb_assert_and_check_return_val(data, 0); - - // data - return tb_buffer_size(&data->buffer); -} -tb_buffer_ref_t tb_oc_data_buffer(tb_object_ref_t object) -{ - // check - tb_oc_data_t* data = tb_oc_data_cast(object); - tb_assert_and_check_return_val(data, tb_null); - - // buffer - return &data->buffer; -} -tb_bool_t tb_oc_data_writ_to_url(tb_object_ref_t object, tb_char_t const* url) -{ - // check - tb_oc_data_t* data = tb_oc_data_cast(object); - tb_assert_and_check_return_val(data && tb_oc_data_getp((tb_object_ref_t)data) && url, tb_false); - - // make stream - tb_stream_ref_t stream = tb_stream_init_from_url(url); - tb_assert_and_check_return_val(stream, tb_false); - - // ctrl - if (tb_stream_type(stream) == TB_STREAM_TYPE_FILE) - tb_stream_ctrl(stream, TB_STREAM_CTRL_FILE_SET_MODE, TB_FILE_MODE_WO | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC); - - // open stream - tb_bool_t ok = tb_false; - if (tb_stream_open(stream)) - { - // writ stream - if (tb_stream_bwrit(stream, (tb_byte_t const*)tb_oc_data_getp((tb_object_ref_t)data), tb_oc_data_size((tb_object_ref_t)data))) ok = tb_true; - } - - // exit stream - tb_stream_exit(stream); - - // ok? - return ok; -} diff --git a/core/src/tbox/src/tbox/object/data.h b/core/src/tbox/src/tbox/object/data.h deleted file mode 100644 index c78fa0b85..000000000 --- a/core/src/tbox/src/tbox/object/data.h +++ /dev/null @@ -1,117 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file data.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DATA_H -#define TB_OBJECT_DATA_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init data from url - * - * @param data the data - * @param size the size - * - * @return the data object - */ -tb_object_ref_t tb_oc_data_init_from_url(tb_char_t const* url); - -/*! init data from data - * - * @param data the data - * @param size the size - * - * @return the data object - */ -tb_object_ref_t tb_oc_data_init_from_data(tb_pointer_t data, tb_size_t size); - -/*! init data from buffer - * - * @param buffer the buffer - * - * @return the data object - */ -tb_object_ref_t tb_oc_data_init_from_buffer(tb_buffer_ref_t buffer); - -/*! get the data - * - * @param data the data object - * - * @return the data address - */ -tb_pointer_t tb_oc_data_getp(tb_object_ref_t data); - -/*! set the data - * - * @param data the data object - * @param addr the data address - * @param size the data size - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_data_setp(tb_object_ref_t data, tb_pointer_t addr, tb_size_t size); - -/*! the data size - * - * @param data the data object - * - * @return the data size - */ -tb_size_t tb_oc_data_size(tb_object_ref_t data); - -/*! the data buffer - * - * @param data the data object - * - * @return the data buffer - */ -tb_buffer_ref_t tb_oc_data_buffer(tb_object_ref_t data); - -/*! writ data to url - * - * @param data the data object - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_data_writ_to_url(tb_object_ref_t data, tb_char_t const* url); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/date.c b/core/src/tbox/src/tbox/object/date.c deleted file mode 100644 index c1e24f496..000000000 --- a/core/src/tbox/src/tbox/object/date.c +++ /dev/null @@ -1,172 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file date.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_date" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" -#include "../utils/utils.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the date type -typedef struct __tb_oc_date_t -{ - // the object base - tb_object_t base; - - // the date time - tb_time_t time; - -}tb_oc_date_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_oc_date_t* tb_oc_date_cast(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_DATE, tb_null); - - // cast - return (tb_oc_date_t*)object; -} -static tb_object_ref_t tb_oc_date_copy(tb_object_ref_t object) -{ - return tb_oc_date_init_from_time(tb_oc_date_time(object)); -} -static tb_void_t tb_oc_date_exit(tb_object_ref_t object) -{ - if (object) tb_free(object); -} -static tb_void_t tb_oc_date_clear(tb_object_ref_t object) -{ - tb_oc_date_t* date = tb_oc_date_cast(object); - if (date) date->time = 0; -} -static tb_oc_date_t* tb_oc_date_init_base() -{ - // done - tb_bool_t ok = tb_false; - tb_oc_date_t* date = tb_null; - do - { - // make date - date = tb_malloc0_type(tb_oc_date_t); - tb_assert_and_check_break(date); - - // init date - if (!tb_object_init((tb_object_ref_t)date, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_DATE)) break; - - // init base - date->base.copy = tb_oc_date_copy; - date->base.exit = tb_oc_date_exit; - date->base.clear = tb_oc_date_clear; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (date) tb_object_exit((tb_object_ref_t)date); - date = tb_null; - } - - // ok? - return date; -} -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_object_ref_t tb_oc_date_init_from_now() -{ - // make - tb_oc_date_t* date = tb_oc_date_init_base(); - tb_assert_and_check_return_val(date, tb_null); - - // init time - date->time = tb_time(); - - // ok - return (tb_object_ref_t)date; -} -tb_object_ref_t tb_oc_date_init_from_time(tb_time_t time) -{ - // make - tb_oc_date_t* date = tb_oc_date_init_base(); - tb_assert_and_check_return_val(date, tb_null); - - // init time - if (time > 0) date->time = time; - - // ok - return (tb_object_ref_t)date; -} -tb_time_t tb_oc_date_time(tb_object_ref_t object) -{ - // check - tb_oc_date_t* date = tb_oc_date_cast(object); - tb_assert_and_check_return_val(date, -1); - - // time - return date->time; -} -tb_bool_t tb_oc_date_time_set(tb_object_ref_t object, tb_time_t time) -{ - // check - tb_oc_date_t* date = tb_oc_date_cast(object); - tb_assert_and_check_return_val(date, tb_false); - - // set time - date->time = time; - - // ok - return tb_true; -} -tb_bool_t tb_oc_date_time_set_now(tb_object_ref_t object) -{ - // check - tb_oc_date_t* date = tb_oc_date_cast(object); - tb_assert_and_check_return_val(date, tb_false); - - // set time - date->time = tb_time(); - - // ok - return tb_true; -} diff --git a/core/src/tbox/src/tbox/object/date.h b/core/src/tbox/src/tbox/object/date.h deleted file mode 100644 index 7046b6499..000000000 --- a/core/src/tbox/src/tbox/object/date.h +++ /dev/null @@ -1,88 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file date.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DATE_H -#define TB_OBJECT_DATE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init date from now - * - * @return the date object - */ -tb_object_ref_t tb_oc_date_init_from_now(tb_noarg_t); - -/*! init date from time - * - * @param the date time - * - * @return the date object - */ -tb_object_ref_t tb_oc_date_init_from_time(tb_time_t time); - -/*! the date time - * - * @param the date object - * - * @return the date time - */ -tb_time_t tb_oc_date_time(tb_object_ref_t date); - -/*! set the date time - * - * @param the date object - * @param the date time - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_date_time_set(tb_object_ref_t date, tb_time_t time); - -/*! set the date time for now - * - * @param the date object - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_date_time_set_now(tb_object_ref_t date); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/deprecated/array.h b/core/src/tbox/src/tbox/object/deprecated/array.h deleted file mode 100644 index 6819a0ff2..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/array.h +++ /dev/null @@ -1,49 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file array.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DEPRECATED_ARRAY_H -#define TB_OBJECT_DEPRECATED_ARRAY_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -#define tb_object_array_init tb_oc_array_init -#define tb_object_array_size tb_oc_array_size -#define tb_object_array_item tb_oc_array_item -#define tb_object_array_incr tb_oc_array_incr -#define tb_object_array_itor tb_oc_array_itor -#define tb_object_array_remove tb_oc_array_remove -#define tb_object_array_append tb_oc_array_append -#define tb_object_array_insert tb_oc_array_insert -#define tb_object_array_replace tb_oc_array_replace - -#endif - diff --git a/core/src/tbox/src/tbox/object/deprecated/boolean.h b/core/src/tbox/src/tbox/object/deprecated/boolean.h deleted file mode 100644 index 8bc8a4d28..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/boolean.h +++ /dev/null @@ -1,45 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file boolean.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DEPRECATED_BOOLEAN_H -#define TB_OBJECT_DEPRECATED_BOOLEAN_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -#define tb_object_boolean_init tb_oc_boolean_init -#define tb_object_boolean_true tb_oc_boolean_true -#define tb_object_boolean_false tb_oc_boolean_false -#define tb_object_boolean_bool tb_oc_boolean_bool - - -#endif - diff --git a/core/src/tbox/src/tbox/object/deprecated/data.h b/core/src/tbox/src/tbox/object/deprecated/data.h deleted file mode 100644 index eee8a9900..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/data.h +++ /dev/null @@ -1,47 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file data.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DEPRECATED_DATA_H -#define TB_OBJECT_DEPRECATED_DATA_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -#define tb_object_data_init_from_url tb_oc_data_init_from_url -#define tb_object_data_init_from_data tb_oc_data_init_from_data -#define tb_object_data_init_from_buffer tb_oc_data_init_from_buffer -#define tb_object_data_getp tb_oc_data_getp -#define tb_object_data_setp tb_oc_data_setp -#define tb_object_data_size tb_oc_data_size -#define tb_object_data_buffer tb_oc_data_buffer -#define tb_object_data_writ_to_url tb_oc_data_writ_to_url - -#endif - diff --git a/core/src/tbox/src/tbox/object/deprecated/date.h b/core/src/tbox/src/tbox/object/deprecated/date.h deleted file mode 100644 index c4a0a7a82..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/date.h +++ /dev/null @@ -1,47 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file date.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DEPRECATED_DATE_H -#define TB_OBJECT_DEPRECATED_DATE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -#define tb_object_date_init_from_now tb_oc_date_init_from_now -#define tb_object_date_init_from_time tb_oc_date_init_from_time -#define tb_object_date_time tb_oc_date_time -#define tb_object_date_time_set tb_oc_date_time_set -#define tb_object_date_time_set_now tb_oc_date_time_set_now - - - -#endif - diff --git a/core/src/tbox/src/tbox/object/deprecated/deprecated.h b/core/src/tbox/src/tbox/object/deprecated/deprecated.h deleted file mode 100644 index 281e5a710..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/deprecated.h +++ /dev/null @@ -1,41 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file deprecated.h - * - */ -#ifndef TB_OBJECT_DEPRECATED_H -#define TB_OBJECT_DEPRECATED_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "null.h" -#include "data.h" -#include "date.h" -#include "array.h" -#include "string.h" -#include "number.h" -#include "boolean.h" -#include "dictionary.h" - - -#endif diff --git a/core/src/tbox/src/tbox/object/deprecated/dictionary.h b/core/src/tbox/src/tbox/object/deprecated/dictionary.h deleted file mode 100644 index 927ab4410..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/dictionary.h +++ /dev/null @@ -1,68 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file dictionary.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DEPRECATED_DICTIONARY_H -#define TB_OBJECT_DEPRECATED_DICTIONARY_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ -#define TB_OBJECT_DICTIONARY_SIZE_MICRO (64) -#define TB_OBJECT_DICTIONARY_SIZE_SMALL (256) -#define TB_OBJECT_DICTIONARY_SIZE_LARGE (65536) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the dictionary item type -typedef struct __tb_object_dictionary_item_t -{ - /// the key - tb_char_t const* key; - - /// the value - tb_object_ref_t val; - -}tb_object_dictionary_item_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -#define tb_object_dictionary_init tb_oc_dictionary_init -#define tb_object_dictionary_size tb_oc_dictionary_size -#define tb_object_dictionary_incr tb_oc_dictionary_incr -#define tb_object_dictionary_itor tb_oc_dictionary_itor -#define tb_object_dictionary_value tb_oc_dictionary_value -#define tb_object_dictionary_insert tb_oc_dictionary_insert -#define tb_object_dictionary_remove tb_oc_dictionary_remove - -#endif - diff --git a/core/src/tbox/src/tbox/object/deprecated/null.h b/core/src/tbox/src/tbox/object/deprecated/null.h deleted file mode 100644 index bd4eb3d5d..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/null.h +++ /dev/null @@ -1,42 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file null.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DEPRECATED_NULL_H -#define TB_OBJECT_DEPRECATED_NULL_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -#define tb_object_null_init tb_oc_null_init - - -#endif - diff --git a/core/src/tbox/src/tbox/object/deprecated/number.h b/core/src/tbox/src/tbox/object/deprecated/number.h deleted file mode 100644 index 87e140ecd..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/number.h +++ /dev/null @@ -1,100 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file number.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DEPRECATED_NUMBER_H -#define TB_OBJECT_DEPRECATED_NUMBER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the number type enum -typedef enum __tb_object_number_type_e -{ - TB_NUMBER_TYPE_NONE = 0 -, TB_NUMBER_TYPE_UINT8 = 1 -, TB_NUMBER_TYPE_SINT8 = 2 -, TB_NUMBER_TYPE_UINT16 = 3 -, TB_NUMBER_TYPE_SINT16 = 4 -, TB_NUMBER_TYPE_UINT32 = 5 -, TB_NUMBER_TYPE_SINT32 = 6 -, TB_NUMBER_TYPE_UINT64 = 7 -, TB_NUMBER_TYPE_SINT64 = 8 -, TB_NUMBER_TYPE_FLOAT = 9 -, TB_NUMBER_TYPE_DOUBLE = 10 - -}tb_object_number_type_e; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -#define tb_object_number_init_from_uint8 tb_oc_number_init_from_uint8 -#define tb_object_number_init_from_sint8 tb_oc_number_init_from_sint8 -#define tb_object_number_init_from_uint16 tb_oc_number_init_from_uint16 -#define tb_object_number_init_from_sint16 tb_oc_number_init_from_sint16 -#define tb_object_number_init_from_uint32 tb_oc_number_init_from_uint32 -#define tb_object_number_init_from_sint32 tb_oc_number_init_from_sint32 -#define tb_object_number_init_from_uint64 tb_oc_number_init_from_uint64 -#define tb_object_number_init_from_sint64 tb_oc_number_init_from_sint64 -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -# define tb_object_number_init_from_float tb_oc_number_init_from_float -# define tb_object_number_init_from_double tb_oc_number_init_from_double -#endif - -#define tb_object_number_type tb_oc_number_type -#define tb_object_number_uint8 tb_oc_number_uint8 -#define tb_object_number_sint8 tb_oc_number_sint8 -#define tb_object_number_uint16 tb_oc_number_uint16 -#define tb_object_number_sint16 tb_oc_number_sint16 -#define tb_object_number_uint32 tb_oc_number_uint32 -#define tb_object_number_sint32 tb_oc_number_sint32 -#define tb_object_number_uint64 tb_oc_number_uint64 -#define tb_object_number_sint64 tb_oc_number_sint64 -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -# define tb_object_number_float tb_oc_number_float -# define tb_object_number_double tb_oc_number_double -#endif - -#define tb_object_number_uint8_set tb_oc_number_uint8_set -#define tb_object_number_sint8_set tb_oc_number_sint8_set -#define tb_object_number_uint16_set tb_oc_number_uint16_set -#define tb_object_number_sint16_set tb_oc_number_sint16_set -#define tb_object_number_uint32_set tb_oc_number_uint32_set -#define tb_object_number_sint32_set tb_oc_number_sint32_set -#define tb_object_number_uint64_set tb_oc_number_uint64_set -#define tb_object_number_sint64_set tb_oc_number_sint64_set -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -# define tb_object_number_floa_set tb_oc_number_float_set -# define tb_object_number_double_set tb_oc_number_double_set -#endif - -#endif - diff --git a/core/src/tbox/src/tbox/object/deprecated/prefix.h b/core/src/tbox/src/tbox/object/deprecated/prefix.h deleted file mode 100644 index 80098707e..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/prefix.h +++ /dev/null @@ -1,35 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_OBJECT_DEPRECATED_PREFIX_H -#define TB_OBJECT_DEPRECATED_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" - - - -#endif diff --git a/core/src/tbox/src/tbox/object/deprecated/string.h b/core/src/tbox/src/tbox/object/deprecated/string.h deleted file mode 100644 index d4f6d7659..000000000 --- a/core/src/tbox/src/tbox/object/deprecated/string.h +++ /dev/null @@ -1,45 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file string.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DEPRECATED_STRING_H -#define TB_OBJECT_DEPRECATED_STRING_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -#define tb_object_string_init_from_cstr tb_oc_string_init_from_cstr -#define tb_object_string_init_from_str tb_oc_string_init_from_str -#define tb_object_string_cstr tb_oc_string_cstr -#define tb_object_string_cstr_set tb_oc_string_cstr_set -#define tb_object_string_size tb_oc_string_size - -#endif - diff --git a/core/src/tbox/src/tbox/object/dictionary.c b/core/src/tbox/src/tbox/object/dictionary.c deleted file mode 100644 index 9e784a697..000000000 --- a/core/src/tbox/src/tbox/object/dictionary.c +++ /dev/null @@ -1,259 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file dictionary.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_dictionary" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" -#include "../string/string.h" -#include "../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ -#ifdef __tb_small__ -# define TB_OC_DICTIONARY_SIZE_DEFAULT TB_OC_DICTIONARY_SIZE_MICRO -#else -# define TB_OC_DICTIONARY_SIZE_DEFAULT TB_OC_DICTIONARY_SIZE_SMALL -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the dictionary type -typedef struct __tb_oc_dictionary_t -{ - // the object base - tb_object_t base; - - // the capacity size - tb_size_t size; - - // the object hash - tb_hash_map_ref_t hash; - - // increase refn? - tb_bool_t incr; - -}tb_oc_dictionary_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_oc_dictionary_t* tb_oc_dictionary_cast(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_DICTIONARY, tb_null); - - // cast - return (tb_oc_dictionary_t*)object; -} -static tb_object_ref_t tb_oc_dictionary_copy(tb_object_ref_t object) -{ - // check - tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); - tb_assert_and_check_return_val(dictionary, tb_null); - - // init copy - tb_oc_dictionary_t* copy = (tb_oc_dictionary_t*)tb_oc_dictionary_init(dictionary->size, dictionary->incr); - tb_assert_and_check_return_val(copy, tb_null); - - // walk copy - tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor((tb_object_ref_t)dictionary)) - { - if (item && item->key) - { - // refn++ - if (item->val) tb_object_retain(item->val); - - // copy - tb_oc_dictionary_insert((tb_object_ref_t)copy, item->key, item->val); - } - } - - // ok - return (tb_object_ref_t)copy; -} -static tb_void_t tb_oc_dictionary_exit(tb_object_ref_t object) -{ - // check - tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); - tb_assert_and_check_return(dictionary); - - // exit hash - if (dictionary->hash) tb_hash_map_exit(dictionary->hash); - dictionary->hash = tb_null; - - // exit it - tb_free(dictionary); -} -static tb_void_t tb_oc_dictionary_clear(tb_object_ref_t object) -{ - tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); - tb_assert_and_check_return(dictionary); - - // clear - if (dictionary->hash) tb_hash_map_clear(dictionary->hash); -} -static tb_oc_dictionary_t* tb_oc_dictionary_init_base() -{ - // done - tb_bool_t ok = tb_false; - tb_oc_dictionary_t* dictionary = tb_null; - do - { - // make dictionary - dictionary = tb_malloc0_type(tb_oc_dictionary_t); - tb_assert_and_check_break(dictionary); - - // init dictionary - if (!tb_object_init((tb_object_ref_t)dictionary, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_DICTIONARY)) break; - - // init base - dictionary->base.copy = tb_oc_dictionary_copy; - dictionary->base.exit = tb_oc_dictionary_exit; - dictionary->base.clear = tb_oc_dictionary_clear; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (dictionary) tb_object_exit((tb_object_ref_t)dictionary); - dictionary = tb_null; - } - - // ok? - return dictionary; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_object_ref_t tb_oc_dictionary_init(tb_size_t size, tb_bool_t incr) -{ - // done - tb_bool_t ok = tb_false; - tb_oc_dictionary_t* dictionary = tb_null; - do - { - // make dictionary - dictionary = tb_oc_dictionary_init_base(); - tb_assert_and_check_break(dictionary); - - // using the default size - if (!size) size = TB_OC_DICTIONARY_SIZE_DEFAULT; - - // init - dictionary->size = size; - dictionary->incr = incr; - - // init hash - dictionary->hash = tb_hash_map_init(size, tb_element_str(tb_true), tb_element_obj()); - tb_assert_and_check_break(dictionary->hash); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (dictionary) tb_oc_dictionary_exit((tb_object_ref_t)dictionary); - dictionary = tb_null; - } - - // ok? - return (tb_object_ref_t)dictionary; -} -tb_size_t tb_oc_dictionary_size(tb_object_ref_t object) -{ - // check - tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); - tb_assert_and_check_return_val(dictionary && dictionary->hash, 0); - - // size - return tb_hash_map_size(dictionary->hash); -} -tb_iterator_ref_t tb_oc_dictionary_itor(tb_object_ref_t object) -{ - tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); - tb_assert_and_check_return_val(dictionary, tb_null); - - // iterator - return (tb_iterator_ref_t)dictionary->hash; -} -tb_object_ref_t tb_oc_dictionary_value(tb_object_ref_t object, tb_char_t const* key) -{ - // check - tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); - tb_assert_and_check_return_val(dictionary && dictionary->hash && key, tb_null); - - // value - return (tb_object_ref_t)tb_hash_map_get(dictionary->hash, key); -} -tb_void_t tb_oc_dictionary_remove(tb_object_ref_t object, tb_char_t const* key) -{ - // check - tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); - tb_assert_and_check_return(dictionary && dictionary->hash && key); - - // del - return tb_hash_map_remove(dictionary->hash, key); -} -tb_void_t tb_oc_dictionary_insert(tb_object_ref_t object, tb_char_t const* key, tb_object_ref_t val) -{ - // check - tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); - tb_assert_and_check_return(dictionary && dictionary->hash && key && val); - - // add - tb_hash_map_insert(dictionary->hash, key, val); - - // refn-- - if (!dictionary->incr) tb_object_exit(val); -} -tb_void_t tb_oc_dictionary_incr(tb_object_ref_t object, tb_bool_t incr) -{ - // check - tb_oc_dictionary_t* dictionary = tb_oc_dictionary_cast(object); - tb_assert_and_check_return(dictionary); - - dictionary->incr = incr; -} diff --git a/core/src/tbox/src/tbox/object/dictionary.h b/core/src/tbox/src/tbox/object/dictionary.h deleted file mode 100644 index 67a144ed2..000000000 --- a/core/src/tbox/src/tbox/object/dictionary.h +++ /dev/null @@ -1,163 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file dictionary.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_DICTIONARY_H -#define TB_OBJECT_DICTIONARY_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ -#define TB_OC_DICTIONARY_SIZE_MICRO (64) -#define TB_OC_DICTIONARY_SIZE_SMALL (256) -#define TB_OC_DICTIONARY_SIZE_LARGE (65536) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the dictionary item type -typedef struct __tb_oc_dictionary_item_t -{ - /// the key - tb_char_t const* key; - - /// the value - tb_object_ref_t val; - -}tb_oc_dictionary_item_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init dictionary - * - * @code - // init dictionary - // {"key1": "hello", "key2" :"world", "key3": 12345, "key4": true} - tb_object_ref_t dict = tb_oc_dictionary_init(0, tb_false); - if (dict) - { - // key1 => hello - tb_oc_dictionary_insert(dict, "key1", tb_oc_string_init_from_cstr("hello")); - - // key2 => world - tb_oc_dictionary_insert(dict, "key2", tb_oc_string_init_from_cstr("world")); - - // key3 => 12345 - tb_oc_dictionary_insert(dict, "key3", tb_oc_number_init_from_sint32(12345)); - - // key4 => true - tb_oc_dictionary_insert(dict, "key4", tb_oc_boolean_true()); - - // exit dictionary - tb_object_exit(dict); - } - * @endcode - * - * @param size the dictionary size, using the default size if be zero - * @param incr is increase refn? - * - * @return the dictionary object - */ -tb_object_ref_t tb_oc_dictionary_init(tb_size_t size, tb_bool_t incr); - -/*! the dictionary size - * - * @param dictionary the dictionary object - * - * @return the dictionary size - */ -tb_size_t tb_oc_dictionary_size(tb_object_ref_t dictionary); - -/*! set the dictionary incr - * - * @param dictionary the dictionary object - * @param incr is increase refn? - */ -tb_void_t tb_oc_dictionary_incr(tb_object_ref_t dictionary, tb_bool_t incr); - -/*! the dictionary iterator - * - * @param dictionary the dictionary object - * - * @return the dictionary iterator - * - * @code - tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(dictionary)) - { - if (item) - { - tb_char_t const* key = item->key; - tb_object_ref_t val = item->val; - - // ... - } - } - * @endcode - */ -tb_iterator_ref_t tb_oc_dictionary_itor(tb_object_ref_t dictionary); - -/*! get the dictionary value - * - * @param dictionary the dictionary object - * @param key the key - * - * @return the dictionary value - */ -tb_object_ref_t tb_oc_dictionary_value(tb_object_ref_t dictionary, tb_char_t const* key); - -/*! insert dictionary item - * - * @param dictionary the dictionary object - * @param key the key - * @param val the value - */ -tb_void_t tb_oc_dictionary_insert(tb_object_ref_t dictionary, tb_char_t const* key, tb_object_ref_t val); - -/*! remove dictionary item - * - * @param dictionary the dictionary object - * @param key the key - */ -tb_void_t tb_oc_dictionary_remove(tb_object_ref_t dictionary, tb_char_t const* key); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/impl.h b/core/src/tbox/src/tbox/object/impl/impl.h deleted file mode 100644 index ad484e737..000000000 --- a/core/src/tbox/src/tbox/object/impl/impl.h +++ /dev/null @@ -1,36 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file impl.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_H -#define TB_OBJECT_IMPL_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" -#include "reader/reader.h" -#include "writer/writer.h" - -#endif diff --git a/core/src/tbox/src/tbox/object/impl/object.c b/core/src/tbox/src/tbox/object/impl/object.c deleted file mode 100644 index d73bcf194..000000000 --- a/core/src/tbox/src/tbox/object/impl/object.c +++ /dev/null @@ -1,86 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file object.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "object" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" -#include "reader/reader.h" -#include "writer/writer.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_bool_t tb_object_init_env() -{ - // register reader - if (!tb_oc_reader_set(TB_OBJECT_FORMAT_BIN, tb_oc_bin_reader())) return tb_false; - if (!tb_oc_reader_set(TB_OBJECT_FORMAT_JSON, tb_oc_json_reader())) return tb_false; - if (!tb_oc_reader_set(TB_OBJECT_FORMAT_BPLIST, tb_oc_bplist_reader())) return tb_false; - - // register writer - if (!tb_oc_writer_set(TB_OBJECT_FORMAT_BIN, tb_oc_bin_writer())) return tb_false; - if (!tb_oc_writer_set(TB_OBJECT_FORMAT_JSON, tb_oc_json_writer())) return tb_false; - if (!tb_oc_writer_set(TB_OBJECT_FORMAT_BPLIST, tb_oc_bplist_writer())) return tb_false; - - // register reader and writer for xml -#ifdef TB_CONFIG_MODULE_HAVE_XML - if (!tb_oc_reader_set(TB_OBJECT_FORMAT_XML, tb_oc_xml_reader())) return tb_false; - if (!tb_oc_writer_set(TB_OBJECT_FORMAT_XML, tb_oc_xml_writer())) return tb_false; - if (!tb_oc_reader_set(TB_OBJECT_FORMAT_XPLIST, tb_oc_xplist_reader())) return tb_false; - if (!tb_oc_writer_set(TB_OBJECT_FORMAT_XPLIST, tb_oc_xplist_writer())) return tb_false; -#endif - - // ok - return tb_true; -} -tb_void_t tb_object_exit_env() -{ - // remove reader - tb_oc_reader_remove(TB_OBJECT_FORMAT_BIN); - tb_oc_reader_remove(TB_OBJECT_FORMAT_JSON); - tb_oc_reader_remove(TB_OBJECT_FORMAT_BPLIST); - - // remove writer - tb_oc_writer_remove(TB_OBJECT_FORMAT_BIN); - tb_oc_writer_remove(TB_OBJECT_FORMAT_JSON); - tb_oc_writer_remove(TB_OBJECT_FORMAT_BPLIST); - - // remove reader and writer for xml -#ifdef TB_CONFIG_MODULE_HAVE_XML - tb_oc_reader_remove(TB_OBJECT_FORMAT_XML); - tb_oc_writer_remove(TB_OBJECT_FORMAT_XML); - tb_oc_reader_remove(TB_OBJECT_FORMAT_XPLIST); - tb_oc_writer_remove(TB_OBJECT_FORMAT_XPLIST); -#endif -} - diff --git a/core/src/tbox/src/tbox/object/impl/object.h b/core/src/tbox/src/tbox/object/impl/object.h deleted file mode 100644 index 500b19a73..000000000 --- a/core/src/tbox/src/tbox/object/impl/object.h +++ /dev/null @@ -1,58 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file object.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_OBJECT_H -#define TB_OBJECT_IMPL_OBJECT_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* init object envirnoment - * - * @return tb_true or tb_false - */ -tb_bool_t tb_object_init_env(tb_noarg_t); - -// exit object envirnoment -tb_void_t tb_object_exit_env(tb_noarg_t); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/prefix.h b/core/src/tbox/src/tbox/object/impl/prefix.h deleted file mode 100644 index ecdfdb27d..000000000 --- a/core/src/tbox/src/tbox/object/impl/prefix.h +++ /dev/null @@ -1,77 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_PREFIX_H -#define TB_OBJECT_IMPL_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../object.h" -#include "../../stream/stream.h" -#include "../../charset/charset.h" -#include "../../container/container.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// need bytes -#define tb_object_need_bytes(x) \ - (((tb_uint64_t)(x)) < (1ull << 8) ? 1 : \ - (((tb_uint64_t)(x)) < (1ull << 16) ? 2 : \ - (((tb_uint64_t)(x)) < (1ull << 32) ? 4 : 8))) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the object reader type -typedef struct __tb_oc_reader_t -{ - /// the hooker - tb_hash_map_ref_t hooker; - - /// probe format - tb_size_t (*probe)(tb_stream_ref_t stream); - - /// read it - tb_object_ref_t (*read)(tb_stream_ref_t stream); - -}tb_oc_reader_t; - -// the object writer type -typedef struct __tb_oc_writer_t -{ - /// the hooker - tb_hash_map_ref_t hooker; - - /// writ it - tb_long_t (*writ)(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate); - -}tb_oc_writer_t; - -#endif diff --git a/core/src/tbox/src/tbox/object/impl/reader/bin.c b/core/src/tbox/src/tbox/object/impl/reader/bin.c deleted file mode 100644 index 66a78d832..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/bin.c +++ /dev/null @@ -1,550 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file bin.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_reader_bin" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "bin.h" -#include "reader.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the array grow -#ifdef __tb_small__ -# define TB_OC_BIN_READER_ARRAY_GROW (64) -#else -# define TB_OC_BIN_READER_ARRAY_GROW (256) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_object_ref_t tb_oc_bin_reader_func_null(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); - - // ok - return tb_oc_null_init(); -} -static tb_object_ref_t tb_oc_bin_reader_func_date(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); - - // ok - return tb_oc_date_init_from_time((tb_time_t)size); -} -static tb_object_ref_t tb_oc_bin_reader_func_data(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); - - // empty? - if (!size) return tb_oc_data_init_from_data(tb_null, 0); - - // make data - tb_char_t* data = tb_malloc0_cstr((tb_size_t)size); - tb_assert_and_check_return_val(data, tb_null); - - // read data - if (!tb_stream_bread(reader->stream, (tb_byte_t*)data, (tb_size_t)size)) - { - tb_free(data); - return tb_null; - } - - // decode data - { - tb_byte_t* pb = (tb_byte_t*)data; - tb_byte_t* pe = (tb_byte_t*)data + size; - tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff)); - for (; pb < pe; pb++, xb++) *pb ^= xb; - } - - // make the data object - tb_object_ref_t object = tb_oc_data_init_from_data(data, (tb_size_t)size); - - // exit data - tb_free(data); - - // ok? - return object; -} -static tb_object_ref_t tb_oc_bin_reader_func_array(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); - - // empty? - if (!size) return tb_oc_array_init(TB_OC_BIN_READER_ARRAY_GROW, tb_false); - - // init array - tb_object_ref_t array = tb_oc_array_init(TB_OC_BIN_READER_ARRAY_GROW, tb_false); - tb_assert_and_check_return_val(array, tb_null); - - // walk - tb_size_t i = 0; - tb_size_t n = (tb_size_t)size; - for (i = 0; i < n; i++) - { - // the type & size - tb_size_t type = 0; - tb_uint64_t size = 0; - tb_oc_reader_bin_type_size(reader->stream, &type, &size); - - // trace - tb_trace_d("item: type: %lu, size: %llu", type, size); - - // is index? - tb_object_ref_t item = tb_null; - if (!type) - { - // the object index - tb_size_t index = (tb_size_t)size; - - // check - tb_assert_and_check_break(index < tb_vector_size(reader->list)); - - // the item - item = (tb_object_ref_t)tb_iterator_item(reader->list, index); - - // refn++ - if (item) tb_object_retain(item); - } - else - { - // the reader func - tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type); - tb_assert_and_check_break(func); - - // read it - item = func(reader, type, size); - - // save it - tb_vector_insert_tail(reader->list, item); - } - - // check - tb_assert_and_check_break(item); - - // append item - tb_oc_array_append(array, item); - } - - // failed? - if (i != n) - { - if (array) tb_object_exit(array); - array = tb_null; - } - - // ok? - return array; -} -static tb_object_ref_t tb_oc_bin_reader_func_string(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); - - // empty? - if (!size) return tb_oc_string_init_from_cstr(tb_null); - - // make data - tb_char_t* data = tb_malloc0_cstr((tb_size_t)size + 1); - tb_assert_and_check_return_val(data, tb_null); - - // read data - if (!tb_stream_bread(reader->stream, (tb_byte_t*)data, (tb_size_t)size)) - { - tb_free(data); - return tb_null; - } - - // decode string - { - tb_byte_t* pb = (tb_byte_t*)data; - tb_byte_t* pe = (tb_byte_t*)data + size; - tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff)); - for (; pb < pe; pb++, xb++) *pb ^= xb; - } - - // make string - tb_object_ref_t string = tb_oc_string_init_from_cstr(data); - - // exit data - tb_free(data); - - // ok? - return string; -} -static tb_object_ref_t tb_oc_bin_reader_func_number(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); - - // the number type - tb_size_t number_type = (tb_size_t)size; - - // read number - tb_value_t value; - tb_object_ref_t number = tb_null; - switch (number_type) - { - case TB_OC_NUMBER_TYPE_UINT64: - { - // read and init number - if (tb_stream_bread_u64_be(reader->stream, &value.u64)) - number = tb_oc_number_init_from_uint64(value.u64); - } - break; - case TB_OC_NUMBER_TYPE_SINT64: - { - // read and init number - if (tb_stream_bread_s64_be(reader->stream, &value.s64)) - number = tb_oc_number_init_from_sint64(value.s64); - } - break; - case TB_OC_NUMBER_TYPE_UINT32: - { - // read and init number - if (tb_stream_bread_u32_be(reader->stream, &value.u32)) - number = tb_oc_number_init_from_uint32(value.u32); - } - break; - case TB_OC_NUMBER_TYPE_SINT32: - { - // read and init number - if (tb_stream_bread_s32_be(reader->stream, &value.s32)) - number = tb_oc_number_init_from_sint32(value.s32); - } - break; - case TB_OC_NUMBER_TYPE_UINT16: - { - // read and init number - if (tb_stream_bread_u16_be(reader->stream, &value.u16)) - number = tb_oc_number_init_from_uint16(value.u16); - } - break; - case TB_OC_NUMBER_TYPE_SINT16: - { - // read and init number - if (tb_stream_bread_s16_be(reader->stream, &value.s16)) - number = tb_oc_number_init_from_sint16(value.s16); - } - break; - case TB_OC_NUMBER_TYPE_UINT8: - { - // read and init number - if (tb_stream_bread_u8(reader->stream, &value.u8)) - number = tb_oc_number_init_from_uint8(value.u8); - } - break; - case TB_OC_NUMBER_TYPE_SINT8: - { - // read and init number - if (tb_stream_bread_s8(reader->stream, &value.s8)) - number = tb_oc_number_init_from_sint8(value.s8); - } - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - { - // read and init number - if (tb_stream_bread_float_be(reader->stream, &value.f)) - number = tb_oc_number_init_from_float(value.f); - } - break; - case TB_OC_NUMBER_TYPE_DOUBLE: - { - // read and init number - if (tb_stream_bread_double_bbe(reader->stream, &value.d)) - number = tb_oc_number_init_from_double(value.d); - } - break; -#endif - default: - tb_assert_and_check_return_val(0, tb_null); - break; - } - - // ok? - return number; -} -static tb_object_ref_t tb_oc_bin_reader_func_boolean(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); - - // ok? - return tb_oc_boolean_init(size? tb_true : tb_false); -} -static tb_object_ref_t tb_oc_bin_reader_func_dictionary(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null); - - // empty? - if (!size) return tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false); - - // init dictionary - tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false); - tb_assert_and_check_return_val(dictionary, tb_null); - - // walk - tb_size_t i = 0; - tb_size_t n = (tb_size_t)size; - for (i = 0; i < n; i++) - { - // read key - tb_object_ref_t key = tb_null; - do - { - // the type & size - tb_size_t type = 0; - tb_uint64_t size = 0; - tb_oc_reader_bin_type_size(reader->stream, &type, &size); - - // trace - tb_trace_d("key: type: %lu, size: %llu", type, size); - - // is index? - if (!type) - { - // the object index - tb_size_t index = (tb_size_t)size; - - // check - tb_assert_and_check_break(index < tb_vector_size(reader->list)); - - // the item - key = (tb_object_ref_t)tb_iterator_item(reader->list, index); - } - else - { - // check - tb_assert_and_check_break(type == TB_OBJECT_TYPE_STRING); - - // the reader func - tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type); - tb_assert_and_check_break(func); - - // read it - key = func(reader, type, size); - tb_assert_and_check_break(key); - - // save it - tb_vector_insert_tail(reader->list, key); - - // refn-- - tb_object_exit(key); - } - - } while (0); - - // check - tb_assert_and_check_break(key && tb_object_type(key) == TB_OBJECT_TYPE_STRING); - tb_assert_and_check_break(tb_oc_string_size(key) && tb_oc_string_cstr(key)); - - // read val - tb_object_ref_t val = tb_null; - do - { - // the type & size - tb_size_t type = 0; - tb_uint64_t size = 0; - tb_oc_reader_bin_type_size(reader->stream, &type, &size); - - // trace - tb_trace_d("val: type: %lu, size: %llu", type, size); - - // is index? - if (!type) - { - // the object index - tb_size_t index = (tb_size_t)size; - - // check - tb_assert_and_check_break(index < tb_vector_size(reader->list)); - - // the item - val = (tb_object_ref_t)tb_iterator_item(reader->list, index); - - // refn++ - if (val) tb_object_retain(val); - } - else - { - // the reader func - tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type); - tb_assert_and_check_break(func); - - // read it - val = func(reader, type, size); - - // save it - if (val) tb_vector_insert_tail(reader->list, val); - } - - } while (0); - - // check - tb_assert_and_check_break(val); - - // set key => val - tb_oc_dictionary_insert(dictionary, tb_oc_string_cstr(key), val); - } - - // failed? - if (i != n) - { - if (dictionary) tb_object_exit(dictionary); - dictionary = tb_null; - } - - // ok? - return dictionary; -} -static tb_object_ref_t tb_oc_bin_reader_done(tb_stream_ref_t stream) -{ - // read bin header - tb_byte_t data[32] = {0}; - if (!tb_stream_bread(stream, data, 5)) return tb_null; - - // check - if (tb_strnicmp((tb_char_t const*)data, "tbo00", 5)) return tb_null; - - // init - tb_object_ref_t object = tb_null; - tb_oc_bin_reader_t reader = {0}; - - // init reader - reader.stream = stream; - reader.list = tb_vector_init(256, tb_element_obj()); - tb_assert_and_check_return_val(reader.list, tb_null); - - // the type & size - tb_size_t type = 0; - tb_uint64_t size = 0; - tb_oc_reader_bin_type_size(stream, &type, &size); - - // trace - tb_trace_d("root: type: %lu, size: %llu", type, size); - - // the func - tb_oc_bin_reader_func_t func = tb_oc_bin_reader_func(type); - - // check - tb_assert(func); - - // read it - if (func) object = func(&reader, type, size); - - // exit the list - if (reader.list) tb_vector_exit(reader.list); - - // ok? - return object; -} -static tb_size_t tb_oc_bin_reader_probe(tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return_val(stream, 0); - - // need it - tb_byte_t* p = tb_null; - if (!tb_stream_need(stream, &p, 3)) return 0; - tb_assert_and_check_return_val(p, 0); - - // ok? - return !tb_strnicmp((tb_char_t const*)p, "tbo", 3)? 80 : 0; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_reader_t* tb_oc_bin_reader() -{ - // the reader - static tb_oc_reader_t s_reader = {0}; - - // init reader - s_reader.read = tb_oc_bin_reader_done; - s_reader.probe = tb_oc_bin_reader_probe; - - // init hooker - s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_reader.hooker, tb_null); - - // hook reader - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NULL, tb_oc_bin_reader_func_null); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_bin_reader_func_date); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_bin_reader_func_data); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_bin_reader_func_array); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_bin_reader_func_string); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_bin_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_bin_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_bin_reader_func_dictionary); - - // ok - return &s_reader; -} -tb_bool_t tb_oc_bin_reader_hook(tb_size_t type, tb_oc_bin_reader_func_t func) -{ - // check - tb_assert_and_check_return_val(type && func, tb_false); - - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BIN); - tb_assert_and_check_return_val(reader && reader->hooker, tb_false); - - // hook it - tb_hash_map_insert(reader->hooker, (tb_pointer_t)type, func); - - // ok - return tb_true; -} -tb_oc_bin_reader_func_t tb_oc_bin_reader_func(tb_size_t type) -{ - // check - tb_assert_and_check_return_val(type, tb_null); - - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BIN); - tb_assert_and_check_return_val(reader && reader->hooker, tb_null); - - // the func - return (tb_oc_bin_reader_func_t)tb_hash_map_get(reader->hooker, (tb_pointer_t)type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/reader/bin.h b/core/src/tbox/src/tbox/object/impl/reader/bin.h deleted file mode 100644 index 900bde20a..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/bin.h +++ /dev/null @@ -1,90 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file bin.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_READER_BIN_H -#define TB_OBJECT_IMPL_READER_BIN_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the bin reader type -typedef struct __tb_oc_bin_reader_t -{ - /// the stream - tb_stream_ref_t stream; - - /// the object list - tb_vector_ref_t list; - -}tb_oc_bin_reader_t; - -/// the bin reader func type -typedef tb_object_ref_t (*tb_oc_bin_reader_func_t)(tb_oc_bin_reader_t* reader, tb_size_t type, tb_uint64_t size); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the bin reader - * - * @return the bin object reader - */ -tb_oc_reader_t* tb_oc_bin_reader(tb_noarg_t); - -/*! hook the bin reader - * - * @param type the object type - * @param func the reader func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_bin_reader_hook(tb_size_t type, tb_oc_bin_reader_func_t func); - -/*! the bin reader func - * - * @param type the object type - * - * @return the object reader func - */ -tb_oc_bin_reader_func_t tb_oc_bin_reader_func(tb_size_t type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/reader/bplist.c b/core/src/tbox/src/tbox/object/impl/reader/bplist.c deleted file mode 100644 index 6d942cc80..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/bplist.c +++ /dev/null @@ -1,821 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file bplist.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_reader_bplist" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "bplist.h" -#include "reader.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the array grow -#ifdef __tb_small__ -# define TB_OC_BPLIST_READER_ARRAY_GROW (64) -#else -# define TB_OC_BPLIST_READER_ARRAY_GROW (256) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the bplist type enum -typedef enum __tb_oc_bplist_type_e -{ - TB_OC_BPLIST_TYPE_NONE = 0x00 -, TB_OC_BPLIST_TYPE_FALSE = 0x08 -, TB_OC_BPLIST_TYPE_TRUE = 0x09 -, TB_OC_BPLIST_TYPE_UINT = 0x10 -, TB_OC_BPLIST_TYPE_REAL = 0x20 -, TB_OC_BPLIST_TYPE_DATE = 0x30 -, TB_OC_BPLIST_TYPE_DATA = 0x40 -, TB_OC_BPLIST_TYPE_STRING = 0x50 -, TB_OC_BPLIST_TYPE_UNICODE = 0x60 -, TB_OC_BPLIST_TYPE_UID = 0x80 -, TB_OC_BPLIST_TYPE_ARRAY = 0xA0 -, TB_OC_BPLIST_TYPE_SET = 0xC0 -, TB_OC_BPLIST_TYPE_DICT = 0xD0 -, TB_OC_BPLIST_TYPE_MASK = 0xF0 - -}tb_oc_bplist_type_e; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_time_t tb_oc_bplist_reader_time_apple2host(tb_time_t time) -{ - tb_tm_t tm = {0}; - if (tb_localtime(time, &tm)) - { - if (tm.year < 2000) tm.year += 31; - time = tb_mktime(&tm); - } - return time; -} -static __tb_inline__ tb_size_t tb_oc_bplist_bits_get(tb_byte_t const* p, tb_size_t n) -{ - tb_size_t v = 0; - switch (n) - { - case 1: v = tb_bits_get_u8((p)); break; - case 2: v = tb_bits_get_u16_be((p)); break; - case 4: v = tb_bits_get_u32_be((p)); break; - case 8: v = tb_bits_get_u64_be((p)); break; - default: break; - } - return v; -} -static tb_object_ref_t tb_oc_bplist_reader_func_object(tb_oc_bplist_reader_t* reader, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // read the object type - tb_uint8_t type = 0; - tb_bool_t ok = tb_stream_bread_u8(reader->stream, &type); - tb_assert_and_check_return_val(ok, tb_null); - - // read the object type and size - tb_uint8_t size = type & 0x0f; type &= 0xf0; - tb_trace_d("type: %x, size: %x", type, size); - - // the func - tb_oc_bplist_reader_func_t func = tb_oc_bplist_reader_func(type); - tb_assert_and_check_return_val(func, tb_null); - - // read - return func(reader, type, size, item_size); -} -static tb_long_t tb_oc_bplist_reader_func_size(tb_oc_bplist_reader_t* reader, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, -1); - - // read size - tb_object_ref_t object = tb_oc_bplist_reader_func_object(reader, item_size); - tb_assert_and_check_return_val(object, -1); - - tb_long_t size = -1; - if (tb_object_type(object) == TB_OBJECT_TYPE_NUMBER) - size = tb_oc_number_uint32(object); - - // exit - tb_object_exit(object); - - // size - return size; -} -static tb_object_ref_t tb_oc_bplist_reader_func_data(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // init - tb_byte_t* data = tb_null; - tb_object_ref_t object = tb_null; - - // size is too large? - if (size == 0x0f) - { - // read size - tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); - tb_assert_and_check_return_val(val >= 0, tb_null); - size = (tb_size_t)val; - } - - // no empty? - if (size) - { - // make data - data = tb_malloc_bytes(size); - tb_assert_and_check_return_val(data, tb_null); - - // read data - if (tb_stream_bread(reader->stream, data, size)) - object = tb_oc_data_init_from_data(data, size); - } - else object = tb_oc_data_init_from_data(tb_null, 0); - - // exit - if (data) tb_free(data); - - // ok? - return object; -} -static tb_object_ref_t tb_oc_bplist_reader_func_array(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // init - tb_object_ref_t object = tb_null; - - // size is too large? - if (size == 0x0f) - { - // read size - tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); - tb_assert_and_check_return_val(val >= 0, tb_null); - size = (tb_size_t)val; - } - - // init array - object = tb_oc_array_init(size? size : 16, tb_false); - tb_assert_and_check_return_val(object, tb_null); - - // init items data - if (size) - { - tb_byte_t* data = tb_malloc_bytes(sizeof(tb_uint32_t) + (size * item_size)); - if (data) - { - if (tb_stream_bread(reader->stream, data + sizeof(tb_uint32_t), size * item_size)) - { - tb_bits_set_u32_ne(data, (tb_uint32_t)size); - - // FIXME: not using the user private data - tb_object_setp(object, data); - } - else tb_free(data); - } - } - - // ok? - return object; -} -static tb_object_ref_t tb_oc_bplist_reader_func_string(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // init - tb_char_t* utf8 = tb_null; - tb_char_t* utf16 = tb_null; - tb_object_ref_t object = tb_null; - - // read - switch (type) - { - case TB_OC_BPLIST_TYPE_STRING: - { - // size is too large? - if (size == 0x0f) - { - // read size - tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); - tb_assert_and_check_return_val(val >= 0, tb_null); - size = (tb_size_t)val; - } - - // read string - if (size) - { - // init utf8 - utf8 = tb_malloc_cstr(size + 1); - tb_assert_and_check_break(utf8); - - // read utf8 - if (!tb_stream_bread(reader->stream, (tb_byte_t*)utf8, size)) break; - utf8[size] = '\0'; - } - - // init object - object = tb_oc_string_init_from_cstr(utf8); - } - break; - case TB_OC_BPLIST_TYPE_UNICODE: - { -#ifdef TB_CONFIG_MODULE_HAVE_CHARSET - // size is too large? - if (size == 0x0f) - { - // read size - tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); - tb_assert_and_check_return_val(val >= 0, tb_null); - size = (tb_size_t)val; - } - - // read string - if (size) - { - // init utf8 & utf16 data - utf8 = tb_malloc_cstr((size + 1) << 2); - utf16 = tb_malloc_cstr(size << 1); - tb_assert_and_check_break(utf8 && utf16); - - // read utf16 - if (!tb_stream_bread(reader->stream, (tb_byte_t*)utf16, size << 1)) break; - - // utf16 to utf8 - tb_long_t osize = tb_charset_conv_data(TB_CHARSET_TYPE_UTF16, TB_CHARSET_TYPE_UTF8, (tb_byte_t*)utf16, size << 1, (tb_byte_t*)utf8, (size + 1) << 2); - tb_assert_and_check_break(osize > 0 && osize < (tb_long_t)((size + 1) << 2)); - utf8[osize] = '\0'; - - // init object - object = tb_oc_string_init_from_cstr(utf8); - } -#else - // trace - tb_trace1_e("unicode type is not supported, please enable charset module config if you want to use it!"); -#endif - } - break; - default: - break; - } - - // exit - if (utf8) tb_free(utf8); - if (utf16) tb_free(utf16); - - // ok? - return object; -} -static tb_object_ref_t tb_oc_bplist_reader_func_number(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // adjust size - size = (tb_size_t)1 << size; - - // done - tb_value_t value; - tb_object_ref_t object = tb_null; - switch (size) - { - case 1: - { - // read and init object - if (tb_stream_bread_u8(reader->stream, &value.u8)) - object = tb_oc_number_init_from_uint8(value.u8); - } - break; - case 2: - { - // read and init object - if (tb_stream_bread_u16_be(reader->stream, &value.u16)) - object = tb_oc_number_init_from_uint16(value.u16); - } - break; - case 4: - { - switch (type) - { - case TB_OC_BPLIST_TYPE_UID: - case TB_OC_BPLIST_TYPE_UINT: - { - // read and init object - if (tb_stream_bread_u32_be(reader->stream, &value.u32)) - object = tb_oc_number_init_from_uint32(value.u32); - } - break; - case TB_OC_BPLIST_TYPE_REAL: - { -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - // read and init object - if (tb_stream_bread_float_be(reader->stream, &value.f)) - object = tb_oc_number_init_from_float(value.f); -#else - tb_trace_e("real type is not supported! please enable float config."); -#endif - } - break; - default: - tb_assert(0); - break; - } - } - break; - case 8: - { - switch (type) - { - case TB_OC_BPLIST_TYPE_UID: - case TB_OC_BPLIST_TYPE_UINT: - { - // read and init object - if (tb_stream_bread_u64_be(reader->stream, &value.u64)) - object = tb_oc_number_init_from_uint64(value.u64); - } - break; - case TB_OC_BPLIST_TYPE_REAL: - { -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - // read and init object - if (tb_stream_bread_double_bbe(reader->stream, &value.d)) - object = tb_oc_number_init_from_double(value.d); -#else - tb_trace_e("real type is not supported! please enable float config."); -#endif - } - break; - default: - tb_assert(0); - break; - } - } - break; - default: - tb_assert(0); - break; - } - - // ok? - return object; -} -static tb_object_ref_t tb_oc_bplist_reader_func_uid(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_object_ref_t uid = tb_null; - tb_object_ref_t value = tb_null; - do - { - // read uid value - value = tb_oc_bplist_reader_func_number(reader, TB_OC_BPLIST_TYPE_UINT, size, item_size); - tb_assert_and_check_break(value); - - // init uid object - uid = tb_oc_dictionary_init(8, tb_false); - tb_assert_and_check_break(uid); - - // save this uid value - tb_oc_dictionary_insert(uid, "CF$UID", value); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit value - if (value) tb_object_exit(value); - value = tb_null; - } - - // ok? - return uid; -} -static tb_object_ref_t tb_oc_bplist_reader_func_date(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // the date data - tb_object_ref_t data = tb_oc_bplist_reader_func_number(reader, TB_OC_BPLIST_TYPE_REAL, size, item_size); - tb_assert_and_check_return_val(data, tb_null); - - // init date - tb_object_ref_t date = tb_oc_date_init_from_time(tb_oc_bplist_reader_time_apple2host((tb_time_t)tb_oc_number_uint64(data))); - - // exit data - tb_object_exit(data); - - // ok? - return date; -} -static tb_object_ref_t tb_oc_bplist_reader_func_boolean(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) -{ - // init - tb_object_ref_t object = tb_null; - - // read - switch (size) - { - case TB_OC_BPLIST_TYPE_TRUE: - object = tb_oc_boolean_init(tb_true); - break; - case TB_OC_BPLIST_TYPE_FALSE: - object = tb_oc_boolean_init(tb_false); - break; - default: - tb_assert(0); - break; - } - return object; -} -static tb_object_ref_t tb_oc_bplist_reader_func_dictionary(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // init - tb_object_ref_t object = tb_null; - - // size is too large? - if (size == 0x0f) - { - // read size - tb_long_t val = tb_oc_bplist_reader_func_size(reader, item_size); - tb_assert_and_check_return_val(val >= 0, tb_null); - size = (tb_size_t)val; - } - - // init dictionary - object = tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false); - tb_assert_and_check_return_val(object, tb_null); - - // init items data - if (size) - { - item_size <<= 1; - tb_byte_t* data = tb_malloc_bytes(sizeof(tb_uint32_t) + (size * item_size)); - if (data) - { - if (tb_stream_bread(reader->stream, data + sizeof(tb_uint32_t), size * item_size)) - { - tb_bits_set_u32_ne(data, (tb_uint32_t)size); - tb_object_setp(object, data); - } - else tb_free(data); - } - } - - // ok? - return object; -} -static tb_object_ref_t tb_oc_bplist_reader_done(tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return_val(stream, tb_null); - - // init root - tb_object_ref_t root = tb_null; - - // init reader - tb_oc_bplist_reader_t reader = {0}; - reader.stream = stream; - - // init size - tb_hize_t size = tb_stream_size(stream); - tb_assert_and_check_return_val(size, tb_null); - - // init data - tb_byte_t data[32] = {0}; - - // read magic & version - if (!tb_stream_bread(stream, data, 8)) return tb_null; - - // check magic & version - if (tb_strncmp((tb_char_t const*)data, "bplist00", 8)) return tb_null; - - // seek to tail - if (!tb_stream_seek(stream, size - 26)) return tb_null; - - // read offset size - tb_uint8_t offset_size = 0; - if (!tb_stream_bread_u8(stream, &offset_size)) return tb_null; - - // read item size for array and dictionary - tb_uint8_t item_size = 0; - if (!tb_stream_bread_u8(stream, &item_size)) return tb_null; - - // read object count - tb_uint64_t object_count = 0; - if (!tb_stream_bread_u64_be(stream, &object_count)) return tb_null; - - // read root object - tb_uint64_t root_object = 0; - if (!tb_stream_bread_u64_be(stream, &root_object)) return tb_null; - - // read offset table index - tb_uint64_t offset_table_index = 0; - if (!tb_stream_bread_u64_be(stream, &offset_table_index)) return tb_null; - - // trace - tb_trace_d("offset_size: %u", offset_size); - tb_trace_d("item_size: %u", item_size); - tb_trace_d("object_count: %llu", object_count); - tb_trace_d("root_object: %llu", root_object); - tb_trace_d("offset_table_index: %llu", offset_table_index); - - // check - tb_assert_and_check_return_val(item_size && offset_size && object_count, tb_null); - - // init object hash - tb_object_ref_t* object_hash = (tb_object_ref_t*)tb_malloc0(sizeof(tb_object_ref_t) * (tb_size_t)object_count); - tb_assert_and_check_return_val(object_hash, tb_null); - - // done - tb_bool_t failed = tb_false; - do - { - // walk - tb_size_t i = 0; - for (i = 0; i < object_count; i++) - { - // seek to the offset entry - if (!tb_stream_seek(stream, offset_table_index + i * offset_size)) - { - failed = tb_true; - break; - } - - // read the object offset - tb_value_t value; - tb_hize_t offset = 0; - switch (offset_size) - { - case 1: - if (tb_stream_bread_u8(stream, &value.u8)) offset = value.u8; - break; - case 2: - if (tb_stream_bread_u16_be(stream, &value.u16)) offset = value.u16; - break; - case 4: - if (tb_stream_bread_u32_be(stream, &value.u32)) offset = value.u32; - break; - case 8: - if (tb_stream_bread_u64_be(stream, &value.u64)) offset = value.u64; - break; - default: - return tb_null; - break; - } - tb_check_break(!failed); - - // seek to the object offset - if (!tb_stream_seek(stream, offset)) - { - failed = tb_true; - break; - } - - // read object - object_hash[i] = tb_oc_bplist_reader_func_object(&reader, item_size); - } - - // failed? - tb_check_break(!failed); - - // build array and dictionary items - for (i = 0; i < object_count; i++) - { - tb_object_ref_t object = object_hash[i]; - if (object) - { - switch (tb_object_type(object)) - { - case TB_OBJECT_TYPE_ARRAY: - { - // the priv data - tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object); - if (priv) - { - // count - tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv); - if (count) - { - // goto item data - tb_byte_t const* p = priv + sizeof(tb_uint32_t); - // walk items - tb_size_t j = 0; - for (j = 0; j < count; j++) - { - // the item index - tb_size_t item = tb_oc_bplist_bits_get(p + j * item_size, item_size); - tb_assert(item < object_count && object_hash[item]); - - // append item - if (item < object_count && object_hash[item]) - { - tb_object_retain(object_hash[item]); - tb_oc_array_append(object, object_hash[item]); - } - } - } - - // exit priv - tb_free(priv); - tb_object_setp(object, tb_null); - } - } - break; - case TB_OBJECT_TYPE_DICTIONARY: - { - // the priv data - tb_byte_t* priv = (tb_byte_t*)tb_object_getp(object); - if (priv) - { - // count - tb_size_t count = (tb_size_t)tb_bits_get_u32_ne(priv); - if (count) - { - // goto item data - tb_byte_t const* p = priv + sizeof(tb_uint32_t); - - // walk items - tb_size_t j = 0; - for (j = 0; j < count; j++) - { - // the key and val - tb_size_t key = tb_oc_bplist_bits_get(p + j * item_size, item_size); - tb_size_t val = tb_oc_bplist_bits_get(p + (count + j) * item_size, item_size); - tb_assert(key < object_count && object_hash[key]); - tb_assert(val < object_count && object_hash[val]); - - // append the key & val - if (key < object_count && val < object_count && object_hash[key] && object_hash[val]) - { - // key must be string now. - tb_assert(tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING); - if (tb_object_type(object_hash[key]) == TB_OBJECT_TYPE_STRING) - { - // set key => val - tb_char_t const* skey = tb_oc_string_cstr(object_hash[key]); - if (skey) - { - tb_object_retain(object_hash[val]); - tb_oc_dictionary_insert(object, skey, object_hash[val]); - } - tb_assert(skey); - } - } - } - } - - // exit priv - tb_free(priv); - tb_object_setp(object, tb_null); - } - } - break; - default: - break; - } - } - } - - } while (0); - - // exit object hash - if (object_hash) - { - // root - if (root_object < object_count) root = object_hash[root_object]; - - // refn-- - tb_size_t i; - for (i = 0; i < object_count; i++) - { - if (object_hash[i] && i != root_object) - tb_object_exit(object_hash[i]); - } - - // exit object hash - tb_free(object_hash); - object_hash = tb_null; - } - - // ok? - return root; -} -static tb_size_t tb_oc_bplist_reader_probe(tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return_val(stream, 0); - - // need it - tb_byte_t* p = tb_null; - if (!tb_stream_need(stream, &p, 6)) return 0; - tb_assert_and_check_return_val(p, 0); - - // ok? - return !tb_strnicmp((tb_char_t const*)p, "bplist", 6)? 80 : 0; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_reader_t* tb_oc_bplist_reader() -{ - // the reader - static tb_oc_reader_t s_reader = {0}; - - // init reader - s_reader.read = tb_oc_bplist_reader_done; - s_reader.probe = tb_oc_bplist_reader_probe; - - // init hooker - s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_reader.hooker, tb_null); - - // hook reader - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_DATE, tb_oc_bplist_reader_func_date); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_DATA, tb_oc_bplist_reader_func_data); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_UID, tb_oc_bplist_reader_func_uid); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_ARRAY, tb_oc_bplist_reader_func_array); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_STRING, tb_oc_bplist_reader_func_string); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_UNICODE, tb_oc_bplist_reader_func_string); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_UINT, tb_oc_bplist_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_REAL, tb_oc_bplist_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_NONE, tb_oc_bplist_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_SET, tb_oc_bplist_reader_func_dictionary); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)TB_OC_BPLIST_TYPE_DICT, tb_oc_bplist_reader_func_dictionary); - - // ok - return &s_reader; -} -tb_bool_t tb_oc_bplist_reader_hook(tb_size_t type, tb_oc_bplist_reader_func_t func) -{ - // check - tb_assert_and_check_return_val(func, tb_false); - - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BPLIST); - tb_assert_and_check_return_val(reader && reader->hooker, tb_false); - - // hook it - tb_hash_map_insert(reader->hooker, (tb_pointer_t)type, func); - - // ok - return tb_true; -} -tb_oc_bplist_reader_func_t tb_oc_bplist_reader_func(tb_size_t type) -{ - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_BPLIST); - tb_assert_and_check_return_val(reader && reader->hooker, tb_null); - - // the func - return (tb_oc_bplist_reader_func_t)tb_hash_map_get(reader->hooker, (tb_pointer_t)type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/reader/bplist.h b/core/src/tbox/src/tbox/object/impl/reader/bplist.h deleted file mode 100644 index 834ff4714..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/bplist.h +++ /dev/null @@ -1,87 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file bplist.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_READER_BPLIST_H -#define TB_OBJECT_IMPL_READER_BPLIST_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the bplist reader type -typedef struct __tb_oc_bplist_reader_t -{ - /// the stream - tb_stream_ref_t stream; - -}tb_oc_bplist_reader_t; - -/// the bplist reader func type -typedef tb_object_ref_t (*tb_oc_bplist_reader_func_t)(tb_oc_bplist_reader_t* reader, tb_size_t type, tb_size_t size, tb_size_t item_size); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the bplist reader - * - * @return the bplist object reader - */ -tb_oc_reader_t* tb_oc_bplist_reader(tb_noarg_t); - -/*! hook the bplist reader - * - * @param type the object type - * @param func the reader func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_bplist_reader_hook(tb_size_t type, tb_oc_bplist_reader_func_t func); - -/*! the bplist reader func - * - * @param type the object type - * - * @return the object reader func - */ -tb_oc_bplist_reader_func_t tb_oc_bplist_reader_func(tb_size_t type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/reader/json.c b/core/src/tbox/src/tbox/object/impl/reader/json.c deleted file mode 100644 index 0ad7f070d..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/json.c +++ /dev/null @@ -1,607 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file json.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_reader_json" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "json.h" -#include "reader.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the array grow -#ifdef __tb_small__ -# define TB_OC_JSON_READER_ARRAY_GROW (64) -#else -# define TB_OC_JSON_READER_ARRAY_GROW (256) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_object_ref_t tb_oc_json_reader_func_null(tb_oc_json_reader_t* reader, tb_char_t type) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // init data - tb_static_string_t data; - tb_char_t buff[256]; - if (!tb_static_string_init(&data, buff, 256)) return tb_null; - - // done - tb_object_ref_t null = tb_null; - do - { - // append character - tb_static_string_chrcat(&data, type); - - // walk - tb_bool_t failed = tb_false; - while (!failed && tb_stream_left(reader->stream)) - { - // need one character - tb_byte_t* p = tb_null; - if (!tb_stream_need(reader->stream, &p, 1) && p) - { - failed = tb_true; - break; - } - - // the character - tb_char_t ch = *p; - - // append character - if (tb_isalpha(ch)) tb_static_string_chrcat(&data, ch); - else break; - - // skip it - tb_stream_skip(reader->stream, 1); - } - - // failed? - tb_check_break(!failed); - - // check - tb_assert_and_check_break(tb_static_string_size(&data)); - - // trace - tb_trace_d("null: %s", tb_static_string_cstr(&data)); - - // null? - if (!tb_stricmp(tb_static_string_cstr(&data), "null")) null = tb_oc_null_init(); - - } while (0); - - // exit data - tb_static_string_exit(&data); - - // ok? - return null; -} -static tb_object_ref_t tb_oc_json_reader_func_array(tb_oc_json_reader_t* reader, tb_char_t type) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && type == '[', tb_null); - - // init array - tb_object_ref_t array = tb_oc_array_init(TB_OC_JSON_READER_ARRAY_GROW, tb_false); - tb_assert_and_check_return_val(array, tb_null); - - // done - tb_char_t ch; - tb_bool_t ok = tb_true; - while (ok && tb_stream_left(reader->stream)) - { - // read one character - if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break; - - // end? - if (ch == ']') break; - // no space? skip ',' - else if (!tb_isspace(ch) && ch != ',') - { - // the func - tb_oc_json_reader_func_t func = tb_oc_json_reader_func(ch); - tb_assert_and_check_break_state(func, ok, tb_false); - - // read item - tb_object_ref_t item = func(reader, ch); - tb_assert_and_check_break_state(item, ok, tb_false); - - // append item - tb_oc_array_append(array, item); - } - } - - // failed? - if (!ok) - { - // exit it - if (array) tb_object_exit(array); - array = tb_null; - } - - // ok? - return array; -} -static tb_object_ref_t tb_oc_json_reader_func_string(tb_oc_json_reader_t* reader, tb_char_t type) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && (type == '\"' || type == '\''), tb_null); - - // init data - tb_string_t data; - if (!tb_string_init(&data)) return tb_null; - - // walk - tb_char_t ch; - while (tb_stream_left(reader->stream)) - { - // read one character - if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break; - - // end? - if (ch == '\"' || ch == '\'') break; - // the escaped character? - else if (ch == '\\') - { - // read one character - if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break; - - // unicode? - if (ch == 'u') - { -#ifdef TB_CONFIG_MODULE_HAVE_CHARSET - // the unicode string - tb_char_t unicode_str[5]; - if (!tb_stream_bread(reader->stream, (tb_byte_t*)unicode_str, 4)) break; - unicode_str[4] = '\0'; - - // the unicode value - tb_uint16_t unicode_val = tb_s16toi32(unicode_str); - - // the utf8 stream - tb_char_t utf8_data[16] = {0}; - tb_static_stream_t utf8_stream; - tb_static_stream_init(&utf8_stream, (tb_byte_t*)utf8_data, sizeof(utf8_data)); - - // the unicode stream - tb_static_stream_t unicode_stream = {0}; - tb_static_stream_init(&unicode_stream, (tb_byte_t*)&unicode_val, 2); - - // unicode to utf8 - tb_long_t utf8_size = tb_charset_conv_bst(TB_CHARSET_TYPE_UCS2 | TB_CHARSET_TYPE_NE, TB_CHARSET_TYPE_UTF8, &unicode_stream, &utf8_stream); - if (utf8_size > 0) tb_string_cstrncat(&data, utf8_data, utf8_size); -#else - // trace - tb_trace1_e("unicode type is not supported, please enable charset module config if you want to use it!"); - - // only append it - tb_string_chrcat(&data, ch); -#endif - } - // append escaped character - else tb_string_chrcat(&data, ch); - } - // append character - else tb_string_chrcat(&data, ch); - } - - // init string - tb_object_ref_t string = tb_oc_string_init_from_cstr(tb_string_cstr(&data)); - - // trace - tb_trace_d("string: %s", tb_string_cstr(&data)); - - // exit data - tb_string_exit(&data); - - // ok? - return string; -} -static tb_object_ref_t tb_oc_json_reader_func_number(tb_oc_json_reader_t* reader, tb_char_t type) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // init data - tb_static_string_t data; - tb_char_t buff[256]; - if (!tb_static_string_init(&data, buff, 256)) return tb_null; - - // done - tb_object_ref_t number = tb_null; - do - { - // append character - tb_static_string_chrcat(&data, type); - - // walk - tb_bool_t bs = (type == '-')? tb_true : tb_false; - tb_bool_t bf = (type == '.')? tb_true : tb_false; - tb_bool_t failed = tb_false; - while (!failed && tb_stream_left(reader->stream)) - { - // need one character - tb_byte_t* p = tb_null; - if (!tb_stream_need(reader->stream, &p, 1) && p) - { - failed = tb_true; - break; - } - - // the character - tb_char_t ch = *p; - - // is float? - if (!bf && ch == '.') bf = tb_true; - else if (bf && ch == '.') - { - failed = tb_true; - break; - } - - // append character - if (tb_isdigit10(ch) || ch == '.' || ch == 'e' || ch == 'E' || ch == '-' || ch == '+') - tb_static_string_chrcat(&data, ch); - else break; - - // skip it - tb_stream_skip(reader->stream, 1); - } - - // failed? - tb_check_break(!failed); - - // check - tb_assert_and_check_break(tb_static_string_size(&data)); - - // trace - tb_trace_d("number: %s", tb_static_string_cstr(&data)); - - // init number -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - if (bf) number = tb_oc_number_init_from_float(tb_stof(tb_static_string_cstr(&data))); -#else - if (bf) tb_trace_noimpl(); -#endif - else if (bs) - { - tb_sint64_t value = tb_stoi64(tb_static_string_cstr(&data)); - tb_size_t bytes = tb_object_need_bytes(-value); - switch (bytes) - { - case 1: number = tb_oc_number_init_from_sint8((tb_sint8_t)value); break; - case 2: number = tb_oc_number_init_from_sint16((tb_sint16_t)value); break; - case 4: number = tb_oc_number_init_from_sint32((tb_sint32_t)value); break; - case 8: number = tb_oc_number_init_from_sint64((tb_sint64_t)value); break; - default: break; - } - - } - else - { - tb_uint64_t value = tb_stou64(tb_static_string_cstr(&data)); - tb_size_t bytes = tb_object_need_bytes(value); - switch (bytes) - { - case 1: number = tb_oc_number_init_from_uint8((tb_uint8_t)value); break; - case 2: number = tb_oc_number_init_from_uint16((tb_uint16_t)value); break; - case 4: number = tb_oc_number_init_from_uint32((tb_uint32_t)value); break; - case 8: number = tb_oc_number_init_from_uint64((tb_uint64_t)value); break; - default: break; - } - } - - } while (0); - - // exit data - tb_static_string_exit(&data); - - // ok? - return number; -} -static tb_object_ref_t tb_oc_json_reader_func_boolean(tb_oc_json_reader_t* reader, tb_char_t type) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream, tb_null); - - // init data - tb_static_string_t data; - tb_char_t buff[256]; - if (!tb_static_string_init(&data, buff, 256)) return tb_null; - - // done - tb_object_ref_t boolean = tb_null; - do - { - // append character - tb_static_string_chrcat(&data, type); - - // walk - tb_bool_t failed = tb_false; - while (!failed && tb_stream_left(reader->stream)) - { - // need one character - tb_byte_t* p = tb_null; - if (!tb_stream_need(reader->stream, &p, 1) && p) - { - failed = tb_true; - break; - } - - // the character - tb_char_t ch = *p; - - // append character - if (tb_isalpha(ch)) tb_static_string_chrcat(&data, ch); - else break; - - // skip it - tb_stream_skip(reader->stream, 1); - } - - // failed? - tb_check_break(!failed); - - // check - tb_assert_and_check_break(tb_static_string_size(&data)); - - // trace - tb_trace_d("boolean: %s", tb_static_string_cstr(&data)); - - // true? - if (!tb_stricmp(tb_static_string_cstr(&data), "true")) boolean = tb_oc_boolean_init(tb_true); - // false? - else if (!tb_stricmp(tb_static_string_cstr(&data), "false")) boolean = tb_oc_boolean_init(tb_false); - - } while (0); - - // exit data - tb_static_string_exit(&data); - - // ok? - return boolean; -} -static tb_object_ref_t tb_oc_json_reader_func_dictionary(tb_oc_json_reader_t* reader, tb_char_t type) -{ - // check - tb_assert_and_check_return_val(reader && reader->stream && type == '{', tb_null); - - // init key name - tb_static_string_t kname; - tb_char_t kdata[8192]; - if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null; - - // init dictionary - tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false); - tb_assert_and_check_return_val(dictionary, tb_null); - - // walk - tb_char_t ch; - tb_bool_t ok = tb_true; - tb_bool_t bkey = tb_false; - tb_size_t bstr = 0; - while (ok && tb_stream_left(reader->stream)) - { - // read one character - if (!tb_stream_bread_s8(reader->stream, (tb_sint8_t*)&ch)) break; - - // end? - if (ch == '}') break; - // no space? skip ',' - else if (!tb_isspace(ch) && ch != ',') - { - // no key? - if (!bkey) - { - // is str? - if (ch == '\"' || ch == '\'') bstr = !bstr; - // is key end? - else if (!bstr && ch == ':') bkey = tb_true; - // append key - else if (bstr) tb_static_string_chrcat(&kname, ch); - } - // key ok? read val - else - { - // trace - tb_trace_d("key: %s", tb_static_string_cstr(&kname)); - - // the func - tb_oc_json_reader_func_t func = tb_oc_json_reader_func(ch); - tb_assert_and_check_break_state(func, ok, tb_false); - - // read val - tb_object_ref_t val = func(reader, ch); - tb_assert_and_check_break_state(val, ok, tb_false); - - // set key => val - tb_oc_dictionary_insert(dictionary, tb_static_string_cstr(&kname), val); - - // reset key - bstr = 0; - bkey = tb_false; - tb_static_string_clear(&kname); - } - } - } - - // failed? - if (!ok) - { - // exit it - if (dictionary) tb_object_exit(dictionary); - dictionary = tb_null; - } - - // exit key name - tb_static_string_exit(&kname); - - // ok? - return dictionary; -} -static tb_object_ref_t tb_oc_json_reader_done(tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return_val(stream, tb_null); - - // init reader - tb_oc_json_reader_t reader = {0}; - reader.stream = stream; - - // skip spaces - tb_char_t type = '\0'; - while (tb_stream_left(stream)) - { - if (!tb_stream_bread_s8(stream, (tb_sint8_t*)&type)) break; - if (!tb_isspace(type)) break; - } - - // empty? - tb_check_return_val(tb_stream_left(stream), tb_null); - - // the func - tb_oc_json_reader_func_t func = tb_oc_json_reader_func(type); - tb_assert_and_check_return_val(func, tb_null); - - // read it - return func(&reader, type); -} -static tb_size_t tb_oc_json_reader_probe(tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return_val(stream, 0); - - // need it - tb_byte_t* p = tb_null; - if (!tb_stream_need(stream, &p, 5)) return 0; - tb_assert_and_check_return_val(p, 0); - - // probe it - tb_size_t s = 10; - tb_byte_t* e = p + 5; - for (; p < e && *p; p++) - { - if (*p == '{' || *p == '[') - { - s = 50; - break; - } - else if (!tb_isgraph(*p)) - { - s = 0; - break; - } - } - - // ok? - return s; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_reader_t* tb_oc_json_reader() -{ - // the reader - static tb_oc_reader_t s_reader = {0}; - - // init reader - s_reader.read = tb_oc_json_reader_done; - s_reader.probe = tb_oc_json_reader_probe; - - // init hooker - s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint8(), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_reader.hooker, tb_null); - - // hook reader - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'n', tb_oc_json_reader_func_null); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'N', tb_oc_json_reader_func_null); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'[', tb_oc_json_reader_func_array); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'\'', tb_oc_json_reader_func_string); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'\"', tb_oc_json_reader_func_string); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'0', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'1', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'2', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'3', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'4', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'5', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'6', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'7', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'8', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'9', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'.', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'-', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'+', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'e', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'E', tb_oc_json_reader_func_number); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'t', tb_oc_json_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'T', tb_oc_json_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'f', tb_oc_json_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'F', tb_oc_json_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, (tb_pointer_t)'{', tb_oc_json_reader_func_dictionary); - - // ok - return &s_reader; -} -tb_bool_t tb_oc_json_reader_hook(tb_char_t type, tb_oc_json_reader_func_t func) -{ - // check - tb_assert_and_check_return_val(type && func, tb_false); - - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_JSON); - tb_assert_and_check_return_val(reader && reader->hooker, tb_false); - - // hook it - tb_hash_map_insert(reader->hooker, (tb_pointer_t)(tb_size_t)type, func); - - // ok - return tb_true; -} -tb_oc_json_reader_func_t tb_oc_json_reader_func(tb_char_t type) -{ - // check - tb_assert_and_check_return_val(type, tb_null); - - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_JSON); - tb_assert_and_check_return_val(reader && reader->hooker, tb_null); - - // the func - return (tb_oc_json_reader_func_t)tb_hash_map_get(reader->hooker, (tb_pointer_t)(tb_size_t)type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/reader/json.h b/core/src/tbox/src/tbox/object/impl/reader/json.h deleted file mode 100644 index af0170656..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/json.h +++ /dev/null @@ -1,87 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file json.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_READER_JSON_H -#define TB_OBJECT_IMPL_READER_JSON_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the json reader type -typedef struct __tb_oc_json_reader_t -{ - /// the stream - tb_stream_ref_t stream; - -}tb_oc_json_reader_t; - -/// the json reader func type -typedef tb_object_ref_t (*tb_oc_json_reader_func_t)(tb_oc_json_reader_t* reader, tb_char_t type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the json object reader - * - * @return the json object reader - */ -tb_oc_reader_t* tb_oc_json_reader(tb_noarg_t); - -/*! hook the json reader - * - * @param type the object type name - * @param func the reader func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_json_reader_hook(tb_char_t type, tb_oc_json_reader_func_t func); - -/*! the json reader func - * - * @param type the object type name - * - * @return the object reader func - */ -tb_oc_json_reader_func_t tb_oc_json_reader_func(tb_char_t type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/reader/prefix.h b/core/src/tbox/src/tbox/object/impl/reader/prefix.h deleted file mode 100644 index 16bd0a032..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/prefix.h +++ /dev/null @@ -1,88 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_READER_PREFIX_H -#define TB_OBJECT_READER_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * inlines - */ -static __tb_inline__ tb_void_t tb_oc_reader_bin_type_size(tb_stream_ref_t stream, tb_size_t* ptype, tb_uint64_t* psize) -{ - // check - tb_assert_and_check_return(stream); - - // clear it first - if (ptype) *ptype = 0; - if (psize) *psize = 0; - - // the flag - tb_uint8_t flag = 0; - tb_bool_t ok = tb_stream_bread_u8(stream, &flag); - tb_assert_and_check_return(ok); - - // read type and size - tb_size_t type = flag >> 4; - tb_uint64_t size = flag & 0x0f; - if (type == 0xf) - { - tb_uint8_t value = 0; - if (tb_stream_bread_u8(stream, &value)) type = value; - } - - // done - tb_value_t value; - switch (size) - { - case 0xc: - if (tb_stream_bread_u8(stream, &value.u8)) size = value.u8; - break; - case 0xd: - if (tb_stream_bread_u16_be(stream, &value.u16)) size = value.u16; - break; - case 0xe: - if (tb_stream_bread_u32_be(stream, &value.u32)) size = value.u32; - break; - case 0xf: - if (tb_stream_bread_u64_be(stream, &value.u64)) size = value.u64; - break; - default: - break; - } - - // trace -// tb_trace_d("type: %lu, size: %llu", type, size); - - // save - if (ptype) *ptype = type; - if (psize) *psize = size; -} - -#endif diff --git a/core/src/tbox/src/tbox/object/impl/reader/reader.c b/core/src/tbox/src/tbox/object/impl/reader/reader.c deleted file mode 100644 index a914e5ec5..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/reader.c +++ /dev/null @@ -1,111 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file reader.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "reader.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * globals - */ - -// the object reader -static tb_oc_reader_t* g_reader[TB_OBJECT_FORMAT_MAXN] = {tb_null}; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_bool_t tb_oc_reader_set(tb_size_t format, tb_oc_reader_t* reader) -{ - // check - format &= 0x00ff; - tb_assert_and_check_return_val(reader && (format < tb_arrayn(g_reader)), tb_false); - - // exit the older reader if exists - tb_oc_reader_remove(format); - - // set - g_reader[format] = reader; - - // ok - return tb_true; -} -tb_void_t tb_oc_reader_remove(tb_size_t format) -{ - // check - format &= 0x00ff; - tb_assert_and_check_return((format < tb_arrayn(g_reader))); - - // exit it - if (g_reader[format]) - { - // exit hooker - if (g_reader[format]->hooker) tb_hash_map_exit(g_reader[format]->hooker); - g_reader[format]->hooker = tb_null; - - // clear it - g_reader[format] = tb_null; - } -} -tb_oc_reader_t* tb_oc_reader_get(tb_size_t format) -{ - // check - format &= 0x00ff; - tb_assert_and_check_return_val((format < tb_arrayn(g_reader)), tb_null); - - // ok - return g_reader[format]; -} -tb_object_ref_t tb_oc_reader_done(tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return_val(stream, tb_null); - - // probe it - tb_size_t i = 0; - tb_size_t n = tb_arrayn(g_reader); - tb_size_t m = 0; - tb_size_t f = 0; - for (i = 0; i < n && m < 100; i++) - { - // the reader - tb_oc_reader_t* reader = g_reader[i]; - if (reader && reader->probe) - { - // the probe score - tb_size_t score = reader->probe(stream); - if (score > m) - { - m = score; - f = i; - } - } - } - - // ok? read it - return (m && g_reader[f] && g_reader[f]->read)? g_reader[f]->read(stream) : tb_null; -} diff --git a/core/src/tbox/src/tbox/object/impl/reader/reader.h b/core/src/tbox/src/tbox/object/impl/reader/reader.h deleted file mode 100644 index a0823efec..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/reader.h +++ /dev/null @@ -1,83 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file reader.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_READER_H -#define TB_OBJECT_IMPL_READER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "xml.h" -#include "bin.h" -#include "json.h" -#include "xplist.h" -#include "bplist.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! set object reader - * - * @param format the reader format - * @param reader the reader - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_reader_set(tb_size_t format, tb_oc_reader_t* reader); - -/*! get object reader - * - * @param format the reader format - * - * @return the object reader - */ -tb_oc_reader_t* tb_oc_reader_get(tb_size_t format); - -/*! remove object reader - * - * @param format the reader format - */ -tb_void_t tb_oc_reader_remove(tb_size_t format); - -/*! done reader - * - * @param stream the stream - * - * @return the object - */ -tb_object_ref_t tb_oc_reader_done(tb_stream_ref_t stream); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/object/impl/reader/xml.c b/core/src/tbox/src/tbox/object/impl/reader/xml.c deleted file mode 100644 index d6d21fd97..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/xml.c +++ /dev/null @@ -1,647 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file xml.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_reader_xml" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "xml.h" -#include "reader.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the array grow -#ifdef __tb_small__ -# define TB_OC_XML_READER_ARRAY_GROW (64) -#else -# define TB_OC_XML_READER_ARRAY_GROW (256) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_object_ref_t tb_oc_xml_reader_func_null(tb_oc_xml_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // ok - return (tb_object_ref_t)tb_oc_null_init(); -} -static tb_object_ref_t tb_oc_xml_reader_func_date(tb_oc_xml_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_date_init_from_time(0); - - // walk - tb_object_ref_t date = tb_null; - tb_bool_t leave = tb_false; - while (!leave && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // is end? - if (!tb_stricmp(name, "date")) - { - // empty? - if (!date) date = tb_oc_date_init_from_time(0); - - // leave it - leave = tb_true; - } - } - break; - case TB_XML_READER_EVENT_TEXT: - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, leave, tb_true); - tb_trace_d("date: %s", text); - - // done date: %04ld-%02ld-%02ld %02ld:%02ld:%02ld - tb_tm_t tm = {0}; - tb_char_t const* p = text; - tb_char_t const* e = text + tb_strlen(text); - - // init year - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.year = tb_atoi(p); - - // init month - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.month = tb_atoi(p); - - // init day - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.mday = tb_atoi(p); - - // init hour - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.hour = tb_atoi(p); - - // init minute - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.minute = tb_atoi(p); - - // init second - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.second = tb_atoi(p); - - // time - tb_time_t time = tb_mktime(&tm); - tb_assert_and_check_break_state(time >= 0, leave, tb_true); - - // date - date = tb_oc_date_init_from_time(time); - } - break; - default: - break; - } - } - - // ok? - return date; -} -static tb_object_ref_t tb_oc_xml_reader_func_data(tb_oc_xml_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_data_init_from_data(tb_null, 0); - - // walk - tb_object_ref_t data = tb_null; - tb_char_t* base64 = tb_null; - tb_bool_t leave = tb_false; - while (!leave && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // is end? - if (!tb_stricmp(name, "data")) - { - // empty? - if (!data) data = tb_oc_data_init_from_data(tb_null, 0); - - // leave it - leave = tb_true; - } - } - break; - case TB_XML_READER_EVENT_TEXT: - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, leave, tb_true); - tb_trace_d("data: %s", text); - - // base64 - base64 = tb_strdup(text); - tb_char_t* p = base64; - tb_char_t* q = p; - for (; *p; p++) if (!tb_isspace(*p)) *q++ = *p; - *q = '\0'; - - // decode base64 data - tb_char_t const* ib = base64; - tb_size_t in = tb_strlen(base64); - if (in) - { - tb_size_t on = in; - tb_byte_t* ob = tb_malloc0_bytes(on); - tb_assert_and_check_break_state(ob && on, leave, tb_true); - on = tb_base64_decode(ib, in, ob, on); - tb_trace_d("base64: %u => %u", in, on); - - // init data - data = tb_oc_data_init_from_data(ob, on); tb_free(ob); - } - else data = tb_oc_data_init_from_data(tb_null, 0); - tb_assert_and_check_break_state(data, leave, tb_true); - } - break; - default: - break; - } - } - - // exit base64 - if (base64) tb_free(base64); - base64 = tb_null; - - // ok? - return data; -} -static tb_object_ref_t tb_oc_xml_reader_func_array(tb_oc_xml_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_array_init(TB_OC_XML_READER_ARRAY_GROW, tb_false); - - // init array - tb_object_ref_t array = tb_oc_array_init(TB_OC_XML_READER_ARRAY_GROW, tb_false); - tb_assert_and_check_return_val(array, tb_null); - - // done - tb_long_t ok = 0; - while (!ok && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_BEG: - case TB_XML_READER_EVENT_ELEMENT_EMPTY: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, ok, -1); - tb_trace_d("item: %s", name); - - // func - tb_oc_xml_reader_func_t func = tb_oc_xml_reader_func(name); - tb_assert_and_check_break_state(func, ok, -1); - - // read - tb_object_ref_t object = func(reader, event); - - // append object - if (object) tb_oc_array_append(array, object); - } - break; - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, ok, -1); - - // is end? - if (!tb_stricmp(name, "array")) ok = 1; - } - break; - default: - break; - } - } - - // failed? - if (ok < 0) - { - // exit it - if (array) tb_object_exit(array); - array = tb_null; - } - - // ok? - return array; -} -static tb_object_ref_t tb_oc_xml_reader_func_string(tb_oc_xml_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_string_init_from_cstr(tb_null); - - // done - tb_bool_t leave = tb_false; - tb_object_ref_t string = tb_null; - while (!leave && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // is end? - if (!tb_stricmp(name, "string")) - { - // empty? - if (!string) string = tb_oc_string_init_from_cstr(tb_null); - - // leave it - leave = tb_true; - } - } - break; - case TB_XML_READER_EVENT_TEXT: - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, leave, tb_true); - tb_trace_d("string: %s", text); - - // string - string = tb_oc_string_init_from_cstr(text); - tb_assert_and_check_break_state(string, leave, tb_true); - } - break; - default: - break; - } - } - - // ok? - return string; -} -static tb_object_ref_t tb_oc_xml_reader_func_number(tb_oc_xml_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_number_init_from_uint32(0); - - // done - tb_bool_t leave = tb_false; - tb_object_ref_t number = tb_null; - while (!leave && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // is end? - if (!tb_stricmp(name, "number")) leave = tb_true; - } - break; - case TB_XML_READER_EVENT_TEXT: - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, leave, tb_true); - tb_trace_d("number: %s", text); - - // has sign? is float? - tb_size_t s = 0; - tb_size_t f = 0; - tb_char_t const* p = text; - for (; *p; p++) - { - if (!s && *p == '-') s = 1; - if (!f && *p == '.') f = 1; - if (s && f) break; - } - - // number -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - if (f) number = tb_oc_number_init_from_double(tb_atof(text)); -#else - if (f) tb_trace_noimpl(); -#endif - else number = s? tb_oc_number_init_from_sint64(tb_stoi64(text)) : tb_oc_number_init_from_uint64(tb_stou64(text)); - tb_assert_and_check_break_state(number, leave, tb_true); - } - break; - default: - break; - } - } - - // ok? - return number; -} -static tb_object_ref_t tb_oc_xml_reader_func_boolean(tb_oc_xml_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_return_val(name, tb_null); - tb_trace_d("boolean: %s", name); - - // the boolean value - tb_bool_t val = tb_false; - if (!tb_stricmp(name, "true")) val = tb_true; - else if (!tb_stricmp(name, "false")) val = tb_false; - else return tb_null; - - // ok? - return (tb_object_ref_t)tb_oc_boolean_init(val); -} -static tb_object_ref_t tb_oc_xml_reader_func_dictionary(tb_oc_xml_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false); - - // init key name - tb_static_string_t kname; - tb_char_t kdata[8192]; - if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null; - - // init dictionary - tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false); - tb_assert_and_check_return_val(dictionary, tb_null); - - // walk - tb_long_t ok = 0; - tb_bool_t key = tb_false; - while (!ok && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_BEG: - case TB_XML_READER_EVENT_ELEMENT_EMPTY: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, ok, -1); - tb_trace_d("%s", name); - - // is key - if (!tb_stricmp(name, "key")) key = tb_true; - else if (!key) - { - // func - tb_oc_xml_reader_func_t func = tb_oc_xml_reader_func(name); - tb_assert_and_check_break_state(func, ok, -1); - - // read - tb_object_ref_t object = func(reader, event); - tb_trace_d("%s => %p", tb_static_string_cstr(&kname), object); - tb_assert_and_check_break_state(object, ok, -1); - - // set key & value - if (tb_static_string_size(&kname) && dictionary) - tb_oc_dictionary_insert(dictionary, tb_static_string_cstr(&kname), object); - - // clear key name - tb_static_string_clear(&kname); - } - } - break; - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, ok, -1); - - // is end? - if (!tb_stricmp(name, "dict")) ok = 1; - else if (!tb_stricmp(name, "key")) key = tb_false; - } - break; - case TB_XML_READER_EVENT_TEXT: - { - if (key) - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, ok, -1); - - // writ key name - tb_static_string_cstrcpy(&kname, text); - } - } - break; - default: - break; - } - } - - // failed? - if (ok < 0) - { - // exit it - if (dictionary) tb_object_exit(dictionary); - dictionary = tb_null; - } - - // exit key name - tb_static_string_exit(&kname); - - // ok? - return dictionary; -} -static tb_object_ref_t tb_oc_xml_reader_done(tb_stream_ref_t stream) -{ - // init reader - tb_oc_xml_reader_t reader = {0}; - reader.reader = tb_xml_reader_init(); - tb_assert_and_check_return_val(reader.reader, tb_null); - - // open reader - tb_object_ref_t object = tb_null; - if (tb_xml_reader_open(reader.reader, stream, tb_false)) - { - // done - tb_bool_t leave = tb_false; - tb_size_t event = TB_XML_READER_EVENT_NONE; - while (!leave && !object && (event = tb_xml_reader_next(reader.reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_EMPTY: - case TB_XML_READER_EVENT_ELEMENT_BEG: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader.reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // func - tb_oc_xml_reader_func_t func = tb_oc_xml_reader_func(name); - tb_assert_and_check_break_state(func, leave, tb_true); - - // read - object = func(&reader, event); - } - break; - default: - break; - } - } - } - - // exit reader - tb_xml_reader_exit(reader.reader); - - // ok? - return object; -} -static tb_size_t tb_oc_xml_reader_probe(tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return_val(stream, 0); - - // need it - tb_byte_t* p = tb_null; - if (!tb_stream_need(stream, &p, 5)) return 0; - tb_assert_and_check_return_val(p, 0); - - // ok? - return !tb_strnicmp((tb_char_t const*)p, "<?xml", 5)? 50 : 0; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_reader_t* tb_oc_xml_reader() -{ - // the reader - static tb_oc_reader_t s_reader = {0}; - - // init reader - s_reader.read = tb_oc_xml_reader_done; - s_reader.probe = tb_oc_xml_reader_probe; - - // init hooker - s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_str(tb_false), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_reader.hooker, tb_null); - - // hook reader - tb_hash_map_insert(s_reader.hooker, "null", tb_oc_xml_reader_func_null); - tb_hash_map_insert(s_reader.hooker, "date", tb_oc_xml_reader_func_date); - tb_hash_map_insert(s_reader.hooker, "data", tb_oc_xml_reader_func_data); - tb_hash_map_insert(s_reader.hooker, "array", tb_oc_xml_reader_func_array); - tb_hash_map_insert(s_reader.hooker, "string", tb_oc_xml_reader_func_string); - tb_hash_map_insert(s_reader.hooker, "number", tb_oc_xml_reader_func_number); - tb_hash_map_insert(s_reader.hooker, "true", tb_oc_xml_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, "false", tb_oc_xml_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, "dict", tb_oc_xml_reader_func_dictionary); - - // ok - return &s_reader; -} -tb_bool_t tb_oc_xml_reader_hook(tb_char_t const* type, tb_oc_xml_reader_func_t func) -{ - // check - tb_assert_and_check_return_val(type && func, tb_false); - - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_XML); - tb_assert_and_check_return_val(reader && reader->hooker, tb_false); - - // hook it - tb_hash_map_insert(reader->hooker, type, func); - - // ok - return tb_true; -} -tb_oc_xml_reader_func_t tb_oc_xml_reader_func(tb_char_t const* type) -{ - // check - tb_assert_and_check_return_val(type, tb_null); - - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_XML); - tb_assert_and_check_return_val(reader && reader->hooker, tb_null); - - // the func - return (tb_oc_xml_reader_func_t)tb_hash_map_get(reader->hooker, type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/reader/xml.h b/core/src/tbox/src/tbox/object/impl/reader/xml.h deleted file mode 100644 index f46a582fa..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/xml.h +++ /dev/null @@ -1,87 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file xml.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_READER_XML_H -#define TB_OBJECT_IMPL_READER_XML_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the xml reader type -typedef struct __tb_oc_xml_reader_t -{ - /// the xml reader - tb_xml_reader_ref_t reader; - -}tb_oc_xml_reader_t; - -/// the xml reader func type -typedef tb_object_ref_t (*tb_oc_xml_reader_func_t)(tb_oc_xml_reader_t* reader, tb_size_t event); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the xml object reader - * - * @return the xml object reader - */ -tb_oc_reader_t* tb_oc_xml_reader(tb_noarg_t); - -/*! hook the xml reader - * - * @param type the object type name - * @param func the reader func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_xml_reader_hook(tb_char_t const* type, tb_oc_xml_reader_func_t func); - -/*! the xml reader func - * - * @param type the object type name - * - * @return the object reader func - */ -tb_oc_xml_reader_func_t tb_oc_xml_reader_func(tb_char_t const* type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/reader/xplist.c b/core/src/tbox/src/tbox/object/impl/reader/xplist.c deleted file mode 100644 index 3b2b18d1b..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/xplist.c +++ /dev/null @@ -1,653 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file xplist.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_reader_xplist" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "xplist.h" -#include "reader.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the array grow -#ifdef __tb_small__ -# define TB_OC_XPLIST_READER_ARRAY_GROW (64) -#else -# define TB_OC_XPLIST_READER_ARRAY_GROW (256) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_object_ref_t tb_oc_xplist_reader_func_date(tb_oc_xplist_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_date_init_from_time(0); - - // done - tb_bool_t leave = tb_false; - tb_object_ref_t date = tb_null; - while (!leave && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // is end? - if (!tb_stricmp(name, "date")) - { - // empty? - if (!date) date = tb_oc_date_init_from_time(0); - - // leave it - leave = tb_true; - } - } - break; - case TB_XML_READER_EVENT_TEXT: - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, leave, tb_true); - tb_trace_d("date: %s", text); - - // done date: %04ld-%02ld-%02ld %02ld:%02ld:%02ld - tb_tm_t tm = {0}; - tb_char_t const* p = text; - tb_char_t const* e = text + tb_strlen(text); - - // init year - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.year = tb_atoi(p); - - // init month - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.month = tb_atoi(p); - - // init day - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.mday = tb_atoi(p); - - // init hour - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.hour = tb_atoi(p); - - // init minute - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.minute = tb_atoi(p); - - // init second - while (p < e && *p && tb_isdigit(*p)) p++; - while (p < e && *p && !tb_isdigit(*p)) p++; - tb_assert_and_check_break_state(p < e, leave, tb_true); - tm.second = tb_atoi(p); - - // time - tb_time_t time = tb_mktime(&tm); - tb_assert_and_check_break_state(time >= 0, leave, tb_true); - - // date - date = tb_oc_date_init_from_time(time); - } - break; - default: - break; - } - } - - // ok? - return date; -} -static tb_object_ref_t tb_oc_xplist_reader_func_data(tb_oc_xplist_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_data_init_from_data(tb_null, 0); - - // done - tb_bool_t leave = tb_false; - tb_char_t* base64 = tb_null; - tb_object_ref_t data = tb_null; - while (!leave && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // is end? - if (!tb_stricmp(name, "data")) - { - // empty? - if (!data) data = tb_oc_data_init_from_data(tb_null, 0); - - // leave it - leave = tb_true; - } - } - break; - case TB_XML_READER_EVENT_TEXT: - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, leave, tb_true); - tb_trace_d("data: %s", text); - - // base64 - base64 = tb_strdup(text); - tb_char_t* p = base64; - tb_char_t* q = p; - for (; *p; p++) if (!tb_isspace(*p)) *q++ = *p; - *q = '\0'; - - // decode base64 data - tb_char_t const* ib = base64; - tb_size_t in = tb_strlen(base64); - if (in) - { - tb_size_t on = in; - tb_byte_t* ob = tb_malloc0_bytes(on); - tb_assert_and_check_break_state(ob && on, leave, tb_true); - on = tb_base64_decode(ib, in, ob, on); - tb_trace_d("base64: %u => %u", in, on); - - // init data - data = tb_oc_data_init_from_data(ob, on); tb_free(ob); - } - else data = tb_oc_data_init_from_data(tb_null, 0); - tb_assert_and_check_break_state(data, leave, tb_true); - } - break; - default: - break; - } - } - - // free - if (base64) tb_free(base64); - - // ok? - return data; -} -static tb_object_ref_t tb_oc_xplist_reader_func_array(tb_oc_xplist_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_array_init(TB_OC_XPLIST_READER_ARRAY_GROW, tb_false); - - // init array - tb_object_ref_t array = tb_oc_array_init(TB_OC_XPLIST_READER_ARRAY_GROW, tb_false); - tb_assert_and_check_return_val(array, tb_null); - - // done - tb_long_t ok = 0; - while (!ok && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_BEG: - case TB_XML_READER_EVENT_ELEMENT_EMPTY: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, ok, -1); - tb_trace_d("item: %s", name); - - // func - tb_oc_xplist_reader_func_t func = tb_oc_xplist_reader_func(name); - tb_assert_and_check_break_state(func, ok, -1); - - // read - tb_object_ref_t object = func(reader, event); - - // append object - if (object) tb_oc_array_append(array, object); - } - break; - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, ok, -1); - - // is end? - if (!tb_stricmp(name, "array")) ok = 1; - } - break; - default: - break; - } - } - - // failed? - if (ok < 0) - { - // exit it - if (array) tb_object_exit(array); - array = tb_null; - } - - // ok? - return array; -} -static tb_object_ref_t tb_oc_xplist_reader_func_string(tb_oc_xplist_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_string_init_from_cstr(tb_null); - - // done - tb_bool_t leave = tb_false; - tb_object_ref_t string = tb_null; - while (!leave && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // is end? - if (!tb_stricmp(name, "string")) - { - // empty? - if (!string) string = tb_oc_string_init_from_cstr(tb_null); - - // leave it - leave = tb_true; - } - } - break; - case TB_XML_READER_EVENT_TEXT: - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, leave, tb_true); - tb_trace_d("string: %s", text); - - // string - string = tb_oc_string_init_from_cstr(text); - tb_assert_and_check_break_state(string, leave, tb_true); - } - break; - default: - break; - } - } - - // ok? - return string; -} -static tb_object_ref_t tb_oc_xplist_reader_func_number(tb_oc_xplist_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_number_init_from_uint32(0); - - // done - tb_bool_t leave = tb_false; - tb_object_ref_t number = tb_null; - while (!leave && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // is end? - if (!tb_stricmp(name, "integer") || !tb_stricmp(name, "real")) leave = tb_true; - } - break; - case TB_XML_READER_EVENT_TEXT: - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, leave, tb_true); - tb_trace_d("number: %s", text); - - // has sign? is float? - tb_size_t s = 0; - tb_size_t f = 0; - tb_char_t const* p = text; - for (; *p; p++) - { - if (!s && *p == '-') s = 1; - if (!f && *p == '.') f = 1; - if (s && f) break; - } - - // number -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - if (f) number = tb_oc_number_init_from_double(tb_atof(text)); -#else - if (f) tb_trace_noimpl(); -#endif - else number = s? tb_oc_number_init_from_sint64(tb_stoi64(text)) : tb_oc_number_init_from_uint64(tb_stou64(text)); - tb_assert_and_check_break_state(number, leave, tb_true); - } - break; - default: - break; - } - } - - // ok? - return number; -} -static tb_object_ref_t tb_oc_xplist_reader_func_boolean(tb_oc_xplist_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_return_val(name, tb_null); - tb_trace_d("boolean: %s", name); - - // the boolean value - tb_bool_t val = tb_false; - if (!tb_stricmp(name, "true")) val = tb_true; - else if (!tb_stricmp(name, "false")) val = tb_false; - else return tb_null; - - // ok? - return (tb_object_ref_t)tb_oc_boolean_init(val); -} -static tb_object_ref_t tb_oc_xplist_reader_func_dictionary(tb_oc_xplist_reader_t* reader, tb_size_t event) -{ - // check - tb_assert_and_check_return_val(reader && reader->reader && event, tb_null); - - // empty? - if (event == TB_XML_READER_EVENT_ELEMENT_EMPTY) - return tb_oc_dictionary_init(TB_OC_DICTIONARY_SIZE_MICRO, tb_false); - - // init key name - tb_static_string_t kname; - tb_char_t kdata[8192]; - if (!tb_static_string_init(&kname, kdata, 8192)) return tb_null; - - // init dictionary - tb_object_ref_t dictionary = tb_oc_dictionary_init(0, tb_false); - tb_assert_and_check_return_val(dictionary, tb_null); - - // done - tb_long_t ok = 0; - tb_bool_t key = tb_false; - while (!ok && (event = tb_xml_reader_next(reader->reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_BEG: - case TB_XML_READER_EVENT_ELEMENT_EMPTY: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, ok, -1); - tb_trace_d("%s", name); - - // is key - if (!tb_stricmp(name, "key")) key = tb_true; - else if (!key) - { - // func - tb_oc_xplist_reader_func_t func = tb_oc_xplist_reader_func(name); - tb_assert_and_check_break_state(func, ok, -1); - - // read - tb_object_ref_t object = func(reader, event); - tb_trace_d("%s => %p", tb_static_string_cstr(&kname), object); - tb_assert_and_check_break_state(object, ok, -1); - - // set key & value - if (tb_static_string_size(&kname) && dictionary) - tb_oc_dictionary_insert(dictionary, tb_static_string_cstr(&kname), object); - - // clear key name - tb_static_string_clear(&kname); - } - } - break; - case TB_XML_READER_EVENT_ELEMENT_END: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader->reader); - tb_assert_and_check_break_state(name, ok, -1); - - // is end? - if (!tb_stricmp(name, "dict")) ok = 1; - else if (!tb_stricmp(name, "key")) key = tb_false; - } - break; - case TB_XML_READER_EVENT_TEXT: - { - if (key) - { - // text - tb_char_t const* text = tb_xml_reader_text(reader->reader); - tb_assert_and_check_break_state(text, ok, -1); - - // writ key name - tb_static_string_cstrcpy(&kname, text); - } - } - break; - default: - break; - } - } - - // failed - if (ok < 0) - { - // exit it - if (dictionary) tb_object_exit(dictionary); - dictionary = tb_null; - } - - // exit key name - tb_static_string_exit(&kname); - - // ok? - return dictionary; -} -static tb_object_ref_t tb_oc_xplist_reader_done(tb_stream_ref_t stream) -{ - // init reader - tb_oc_xplist_reader_t reader = {0}; - reader.reader = tb_xml_reader_init(); - tb_assert_and_check_return_val(reader.reader, tb_null); - - // open reader - tb_object_ref_t object = tb_null; - if (tb_xml_reader_open(reader.reader, stream, tb_false)) - { - // done - tb_bool_t leave = tb_false; - tb_size_t event = TB_XML_READER_EVENT_NONE; - while (!leave && !object && (event = tb_xml_reader_next(reader.reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_EMPTY: - case TB_XML_READER_EVENT_ELEMENT_BEG: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader.reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // <plist/> ? - if (tb_stricmp(name, "plist")) - { - // func - tb_oc_xplist_reader_func_t func = tb_oc_xplist_reader_func(name); - tb_assert_and_check_break_state(func, leave, tb_true); - - // read - object = func(&reader, event); - } - } - break; - default: - break; - } - } - } - - // exit reader - tb_xml_reader_exit(reader.reader); - - // ok? - return object; -} -static tb_size_t tb_oc_xplist_reader_probe(tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return_val(stream, 0); - - // need it - tb_byte_t* p = tb_null; - if (!tb_stream_need(stream, &p, 5)) return 0; - tb_assert_and_check_return_val(p, 0); - - // is xml data? - if (!tb_strnicmp((tb_char_t const*)p, "<?xml", 5)) - { - // need more data - if (!tb_stream_need(stream, &p, 256)) return 5; - tb_assert_and_check_return_val(p, 5); - - // is xplist? - return tb_strnistr((tb_char_t const*)p, 256, "DOCTYPE plist")? 80 : 10; - } - - // ok? - return 0; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_reader_t* tb_oc_xplist_reader() -{ - // the reader - static tb_oc_reader_t s_reader = {0}; - - // init reader - s_reader.read = tb_oc_xplist_reader_done; - s_reader.probe = tb_oc_xplist_reader_probe; - - // init hooker - s_reader.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_str(tb_false), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_reader.hooker, tb_null); - - // hook reader - tb_hash_map_insert(s_reader.hooker, "date", tb_oc_xplist_reader_func_date); - tb_hash_map_insert(s_reader.hooker, "data", tb_oc_xplist_reader_func_data); - tb_hash_map_insert(s_reader.hooker, "array", tb_oc_xplist_reader_func_array); - tb_hash_map_insert(s_reader.hooker, "string", tb_oc_xplist_reader_func_string); - tb_hash_map_insert(s_reader.hooker, "integer", tb_oc_xplist_reader_func_number); - tb_hash_map_insert(s_reader.hooker, "real", tb_oc_xplist_reader_func_number); - tb_hash_map_insert(s_reader.hooker, "true", tb_oc_xplist_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, "false", tb_oc_xplist_reader_func_boolean); - tb_hash_map_insert(s_reader.hooker, "dict", tb_oc_xplist_reader_func_dictionary); - - // ok - return &s_reader; -} -tb_bool_t tb_oc_xplist_reader_hook(tb_char_t const* type, tb_oc_xplist_reader_func_t func) -{ - // check - tb_assert_and_check_return_val(type && func, tb_false); - - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_XPLIST); - tb_assert_and_check_return_val(reader && reader->hooker, tb_false); - - // hook it - tb_hash_map_insert(reader->hooker, type, func); - - // ok - return tb_true; -} -tb_oc_xplist_reader_func_t tb_oc_xplist_reader_func(tb_char_t const* type) -{ - // check - tb_assert_and_check_return_val(type, tb_null); - - // the reader - tb_oc_reader_t* reader = tb_oc_reader_get(TB_OBJECT_FORMAT_XPLIST); - tb_assert_and_check_return_val(reader && reader->hooker, tb_null); - - // the func - return (tb_oc_xplist_reader_func_t)tb_hash_map_get(reader->hooker, type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/reader/xplist.h b/core/src/tbox/src/tbox/object/impl/reader/xplist.h deleted file mode 100644 index 4ba5d7d4a..000000000 --- a/core/src/tbox/src/tbox/object/impl/reader/xplist.h +++ /dev/null @@ -1,87 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file xplist.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_READER_XPLIST_H -#define TB_OBJECT_IMPL_READER_XPLIST_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the xplist reader type -typedef struct __tb_oc_xplist_reader_t -{ - // the xplist reader - tb_xml_reader_ref_t reader; - -}tb_oc_xplist_reader_t; - -// the xplist reader func type -typedef tb_object_ref_t (*tb_oc_xplist_reader_func_t)(tb_oc_xplist_reader_t* reader, tb_size_t event); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/* the xplist object reader - * - * @return the xplist object reader - */ -tb_oc_reader_t* tb_oc_xplist_reader(tb_noarg_t); - -/* hook the xplist reader - * - * @param type the object type name - * @param func the reader func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_xplist_reader_hook(tb_char_t const* type, tb_oc_xplist_reader_func_t func); - -/* the xplist reader func - * - * @param type the object type name - * - * @return the object reader func - */ -tb_oc_xplist_reader_func_t tb_oc_xplist_reader_func(tb_char_t const* type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/writer/bin.c b/core/src/tbox/src/tbox/object/impl/writer/bin.c deleted file mode 100644 index e85c51425..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/bin.c +++ /dev/null @@ -1,429 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file bin.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_writer_bin" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "bin.h" -#include "writer.h" -#include "../../../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_bool_t tb_oc_bin_writer_func_null(tb_oc_bin_writer_t* writer, tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && writer && writer->stream, tb_false); - - // writ type & null - return tb_oc_writer_bin_type_size(writer->stream, object->type, 0); -} -static tb_bool_t tb_oc_bin_writer_func_date(tb_oc_bin_writer_t* writer, tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && writer && writer->stream, tb_false); - - // writ type & time - return tb_oc_writer_bin_type_size(writer->stream, object->type, (tb_uint64_t)tb_oc_date_time(object)); -} -static tb_bool_t tb_oc_bin_writer_func_data(tb_oc_bin_writer_t* writer, tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && writer && writer->stream, tb_false); - - // the data & size - tb_byte_t const* data = (tb_byte_t const*)tb_oc_data_getp(object); - tb_size_t size = tb_oc_data_size(object); - - // writ type & size - if (!tb_oc_writer_bin_type_size(writer->stream, object->type, size)) return tb_false; - - // empty? - tb_check_return_val(size, tb_true); - - // check - tb_assert_and_check_return_val(data, tb_false); - - // make the encoder data - if (!writer->data) - { - writer->maxn = tb_max(size, 8192); - writer->data = tb_malloc0_bytes(writer->maxn); - } - else if (writer->maxn < size) - { - writer->maxn = size; - writer->data = (tb_byte_t*)tb_ralloc(writer->data, writer->maxn); - } - tb_assert_and_check_return_val(writer->data && size <= writer->maxn, tb_false); - - // copy data to encoder - tb_memcpy(writer->data, data, size); - - // encode data - tb_byte_t const* pb = data; - tb_byte_t const* pe = data + size; - tb_byte_t* qb = writer->data; - tb_byte_t* qe = writer->data + writer->maxn; - tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff)); - for (; pb < pe && qb < qe; pb++, qb++, xb++) *qb = *pb ^ xb; - - // writ it - return tb_stream_bwrit(writer->stream, writer->data, size); -} -static tb_bool_t tb_oc_bin_writer_func_array(tb_oc_bin_writer_t* writer, tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && writer && writer->stream && writer->ohash, tb_false); - - // writ type & size - if (!tb_oc_writer_bin_type_size(writer->stream, object->type, tb_oc_array_size(object))) return tb_false; - - // walk - tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object)) - { - if (item) - { - // exists? - tb_size_t index = (tb_size_t)tb_hash_map_get(writer->ohash, item); - if (index) - { - // writ index - if (!tb_oc_writer_bin_type_size(writer->stream, 0, (tb_uint64_t)(index - 1))) return tb_false; - } - else - { - // the func - tb_oc_bin_writer_func_t func = tb_oc_bin_writer_func(item->type); - tb_assert_and_check_continue(func); - - // writ it - if (!func(writer, item)) return tb_false; - - // save index - tb_hash_map_insert(writer->ohash, item, (tb_cpointer_t)(++writer->index)); - } - } - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_bin_writer_func_string(tb_oc_bin_writer_t* writer, tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && writer && writer->stream, tb_false); - - // the data & size - tb_char_t const* data = tb_oc_string_cstr(object); - tb_size_t size = tb_oc_string_size(object); - - // writ type & size - if (!tb_oc_writer_bin_type_size(writer->stream, object->type, size)) return tb_false; - - // empty? - tb_check_return_val(size, tb_true); - - // check - tb_assert_and_check_return_val(data, tb_false); - - // make the encoder data - if (!writer->data) - { - writer->maxn = tb_max(size, 8192); - writer->data = tb_malloc0_bytes(writer->maxn); - } - else if (writer->maxn < size) - { - writer->maxn = size; - writer->data = (tb_byte_t*)tb_ralloc(writer->data, writer->maxn); - } - tb_assert_and_check_return_val(writer->data && size <= writer->maxn, tb_false); - - // copy data to encoder - tb_memcpy(writer->data, data, size); - - // encode data - tb_byte_t const* pb = (tb_byte_t const*)data; - tb_byte_t const* pe = (tb_byte_t const*)data + size; - tb_byte_t* qb = writer->data; - tb_byte_t* qe = writer->data + writer->maxn; - tb_byte_t xb = (tb_byte_t)(((size >> 8) & 0xff) | (size & 0xff)); - for (; pb < pe && qb < qe && *pb; pb++, qb++, xb++) *qb = *pb ^ xb; - - // writ it - return tb_stream_bwrit(writer->stream, writer->data, size); -} -static tb_bool_t tb_oc_bin_writer_func_number(tb_oc_bin_writer_t* writer, tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && writer && writer->stream, tb_false); - - // writ type - if (!tb_oc_writer_bin_type_size(writer->stream, object->type, (tb_uint64_t)tb_oc_number_type(object))) return tb_false; - - // writ number - switch (tb_oc_number_type(object)) - { - case TB_OC_NUMBER_TYPE_UINT64: - if (!tb_stream_bwrit_u64_be(writer->stream, tb_oc_number_uint64(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT64: - if (!tb_stream_bwrit_s64_be(writer->stream, tb_oc_number_sint64(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT32: - if (!tb_stream_bwrit_u32_be(writer->stream, tb_oc_number_uint32(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT32: - if (!tb_stream_bwrit_s32_be(writer->stream, tb_oc_number_sint32(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT16: - if (!tb_stream_bwrit_u16_be(writer->stream, tb_oc_number_uint16(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT16: - if (!tb_stream_bwrit_s16_be(writer->stream, tb_oc_number_sint16(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT8: - if (!tb_stream_bwrit_u8(writer->stream, tb_oc_number_uint8(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT8: - if (!tb_stream_bwrit_s8(writer->stream, tb_oc_number_sint8(object))) return tb_false; - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - { - tb_byte_t data[4]; - tb_bits_set_float_be(data, tb_oc_number_float(object)); - if (!tb_stream_bwrit(writer->stream, data, 4)) return tb_false; - } - break; - case TB_OC_NUMBER_TYPE_DOUBLE: - { - tb_byte_t data[8]; - tb_bits_set_double_bbe(data, tb_oc_number_double(object)); - if (!tb_stream_bwrit(writer->stream, data, 8)) return tb_false; - } - break; -#endif - default: - tb_assert_and_check_return_val(0, tb_false); - break; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_bin_writer_func_boolean(tb_oc_bin_writer_t* writer, tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && writer && writer->stream, tb_false); - - // writ type & bool - return tb_oc_writer_bin_type_size(writer->stream, object->type, tb_oc_boolean_bool(object)); -} -static tb_bool_t tb_oc_bin_writer_func_dictionary(tb_oc_bin_writer_t* writer, tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && writer && writer->stream && writer->ohash, tb_false); - - // writ type & size - if (!tb_oc_writer_bin_type_size(writer->stream, object->type, tb_oc_dictionary_size(object))) return tb_false; - - // walk - tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object)) - { - if (item) - { - tb_char_t const* key = item->key; - tb_object_ref_t val = item->val; - if (key && val) - { - // writ key - { - // exists? - tb_size_t index = (tb_size_t)tb_hash_map_get(writer->shash, key); - if (index) - { - // writ index - if (!tb_oc_writer_bin_type_size(writer->stream, 0, (tb_uint64_t)(index - 1))) return tb_false; - } - else - { - // the func - tb_oc_bin_writer_func_t func = tb_oc_bin_writer_func(TB_OBJECT_TYPE_STRING); - tb_assert_and_check_return_val(func, tb_false); - - // make the key object - tb_object_ref_t okey = tb_oc_string_init_from_cstr(key); - tb_assert_and_check_return_val(okey, tb_false); - - // writ it - if (!func(writer, okey)) return tb_false; - - // exit it - tb_object_exit(okey); - - // save index - tb_hash_map_insert(writer->shash, key, (tb_cpointer_t)(++writer->index)); - } - } - - // writ val - { - // exists? - tb_size_t index = (tb_size_t)tb_hash_map_get(writer->ohash, val); - if (index) - { - // writ index - if (!tb_oc_writer_bin_type_size(writer->stream, 0, (tb_uint64_t)(index - 1))) return tb_false; - } - else - { - // the func - tb_oc_bin_writer_func_t func = tb_oc_bin_writer_func(val->type); - tb_assert_and_check_return_val(func, tb_false); - - // writ it - if (!func(writer, val)) return tb_false; - - // save index - tb_hash_map_insert(writer->ohash, val, (tb_cpointer_t)(++writer->index)); - } - } - } - } - } - - // ok - return tb_true; -} -static tb_long_t tb_oc_bin_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate) -{ - // check - tb_assert_and_check_return_val(object && stream, -1); - - // the func - tb_oc_bin_writer_func_t func = tb_oc_bin_writer_func(object->type); - tb_assert_and_check_return_val(func, -1); - - // the begin offset - tb_hize_t bof = tb_stream_offset(stream); - - // writ bin header - if (!tb_stream_bwrit(stream, (tb_byte_t const*)"tbo00", 5)) return -1; - - // done - tb_oc_bin_writer_t writer = {0}; - do - { - // init writer - writer.stream = stream; - writer.ohash = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_ptr(tb_null, tb_null), tb_element_uint32()); - writer.shash = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_str(tb_true), tb_element_uint32()); - tb_assert_and_check_break(writer.shash && writer.ohash); - - // writ - if (!func(&writer, object)) break; - - // sync - if (!tb_stream_sync(stream, tb_true)) break; - - } while (0); - - // exit the hash - if (writer.ohash) tb_hash_map_exit(writer.ohash); - if (writer.shash) tb_hash_map_exit(writer.shash); - - // exit the data - if (writer.data) tb_free(writer.data); - - // the end offset - tb_hize_t eof = tb_stream_offset(stream); - - // ok? - return eof >= bof? (tb_long_t)(eof - bof) : -1; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_writer_t* tb_oc_bin_writer() -{ - // the writer - static tb_oc_writer_t s_writer = {0}; - - // init writer - s_writer.writ = tb_oc_bin_writer_done; - - // init hooker - s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_writer.hooker, tb_null); - - // hook writer - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NULL, tb_oc_bin_writer_func_null); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_bin_writer_func_date); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_bin_writer_func_data); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_bin_writer_func_array); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_bin_writer_func_string); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_bin_writer_func_number); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_bin_writer_func_boolean); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_bin_writer_func_dictionary); - - // ok - return &s_writer; -} -tb_bool_t tb_oc_bin_writer_hook(tb_size_t type, tb_oc_bin_writer_func_t func) -{ - // check - tb_assert_and_check_return_val(func, tb_false); - - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_BIN); - tb_assert_and_check_return_val(writer && writer->hooker, tb_false); - - // hook it - tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func); - - // ok - return tb_true; -} -tb_oc_bin_writer_func_t tb_oc_bin_writer_func(tb_size_t type) -{ - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_BIN); - tb_assert_and_check_return_val(writer && writer->hooker, tb_null); - - // the func - return (tb_oc_bin_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/writer/bin.h b/core/src/tbox/src/tbox/object/impl/writer/bin.h deleted file mode 100644 index fdc68d09a..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/bin.h +++ /dev/null @@ -1,102 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file bin.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_WRITER_BIN_H -#define TB_OBJECT_IMPL_WRITER_BIN_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the object bin writer type -typedef struct __tb_oc_bin_writer_t -{ - /// the stream - tb_stream_ref_t stream; - - /// the object hash - tb_hash_map_ref_t ohash; - - /// the string hash - tb_hash_map_ref_t shash; - - /// the object index - tb_size_t index; - - /// the encoder data - tb_byte_t* data; - - /// the encoder maxn - tb_size_t maxn; - -}tb_oc_bin_writer_t; - -/// the bin writer func type -typedef tb_bool_t (*tb_oc_bin_writer_func_t)(tb_oc_bin_writer_t* writer, tb_object_ref_t object); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the bin object writer - * - * @return the bin object writer - */ -tb_oc_writer_t* tb_oc_bin_writer(tb_noarg_t); - -/*! hook the bin writer - * - * @param type the object type - * @param func the writer func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_bin_writer_hook(tb_size_t type, tb_oc_bin_writer_func_t func); - -/*! the bin writer func - * - * @param type the object type - * - * @return the object writer func - */ -tb_oc_bin_writer_func_t tb_oc_bin_writer_func(tb_size_t type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/writer/bplist.c b/core/src/tbox/src/tbox/object/impl/writer/bplist.c deleted file mode 100644 index d3887aeca..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/bplist.c +++ /dev/null @@ -1,806 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file bplist.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_writer_bplist" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "bplist.h" -#include "writer.h" -#include "../../../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// set bits -#define tb_oc_bplist_writer_bits_set(p, v, n) \ -do { \ - switch ((n)) \ - { \ - case 1: tb_bits_set_u8((p), (tb_uint8_t)(v)); break; \ - case 2: tb_bits_set_u16_be((p), (tb_uint16_t)(v)); break; \ - case 4: tb_bits_set_u32_be((p), (tb_uint32_t)(v)); break; \ - case 8: tb_bits_set_u64_be((p), (tb_uint64_t)(v)); break; \ - default: break; \ - } \ -} while (0) - -// number -#define tb_oc_bplist_writer_init_number(x) \ -(((tb_uint64_t)(x)) < (1ull << 8) ? tb_oc_number_init_from_uint8((tb_uint8_t)(x)) : \ -(((tb_uint64_t)(x)) < (1ull << 16) ? tb_oc_number_init_from_uint16((tb_uint16_t)(x)) : \ -(((tb_uint64_t)(x)) < (1ull << 32) ? tb_oc_number_init_from_uint32((tb_uint32_t)(x)) : tb_oc_number_init_from_uint64((x))))) - -// object list grow -#ifdef __tb_small__ -# define TB_OBJECT_BPLIST_LIST_GROW (64) -#else -# define TB_OBJECT_BPLIST_LIST_GROW (256) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the bplist type enum -typedef enum __tb_oc_bplist_type_e -{ - TB_OBJECT_BPLIST_TYPE_NONE = 0x00 -, TB_OBJECT_BPLIST_TYPE_FALSE = 0x08 -, TB_OBJECT_BPLIST_TYPE_TRUE = 0x09 -, TB_OBJECT_BPLIST_TYPE_UINT = 0x10 -, TB_OBJECT_BPLIST_TYPE_REAL = 0x20 -, TB_OBJECT_BPLIST_TYPE_DATE = 0x30 -, TB_OBJECT_BPLIST_TYPE_DATA = 0x40 -, TB_OBJECT_BPLIST_TYPE_STRING = 0x50 -, TB_OBJECT_BPLIST_TYPE_UNICODE = 0x60 -, TB_OBJECT_BPLIST_TYPE_UID = 0x70 -, TB_OBJECT_BPLIST_TYPE_ARRAY = 0xA0 -, TB_OBJECT_BPLIST_TYPE_SET = 0xC0 -, TB_OBJECT_BPLIST_TYPE_DICT = 0xD0 -, TB_OBJECT_BPLIST_TYPE_MASK = 0xF0 - -}tb_oc_bplist_type_e; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * declaration - */ -static tb_bool_t tb_oc_bplist_writer_func_number(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -static __tb_inline__ tb_time_t tb_oc_bplist_writer_time_host2apple(tb_time_t time) -{ - tb_tm_t tm = {0}; - if (tb_localtime(time, &tm)) - { - if (tm.year >= 31) tm.year -= 31; - time = tb_mktime(&tm); - } - return time; -} -#endif -static tb_bool_t tb_oc_bplist_writer_func_rdata(tb_oc_bplist_writer_t* writer, tb_uint8_t bype, tb_byte_t const* data, tb_size_t size, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream && !data == !size, tb_false); - - // writ flag - tb_uint8_t flag = bype | (tb_uint8_t)(size < 15 ? size : 0xf); - if (!tb_stream_bwrit_u8(writer->stream, flag)) return tb_false; - - // writ size - if (size >= 15) - { - // init object - tb_object_ref_t object = tb_oc_bplist_writer_init_number(size); - tb_assert_and_check_return_val(object, tb_false); - - // writ it - if (!tb_oc_bplist_writer_func_number(writer, object, item_size)) - { - tb_object_exit(object); - return tb_false; - } - - // exit object - tb_object_exit(object); - } - - // unicode? adjust size - if (bype == TB_OBJECT_BPLIST_TYPE_UNICODE) size <<= 1; - - // writ data - if (data) if (!tb_stream_bwrit(writer->stream, data, size)) return tb_false; - - // ok - return tb_true; -} -static tb_bool_t tb_oc_bplist_writer_func_date(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream && object, tb_false); - -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - // writ date time - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_DATE | 3)) return tb_false; - if (!tb_stream_bwrit_double_bbe(writer->stream, (tb_double_t)tb_oc_bplist_writer_time_host2apple(tb_oc_date_time(object)))) return tb_false; -#else - tb_assert_and_check_return_val(0, tb_false); -#endif - - // ok - return tb_true; -} -static tb_bool_t tb_oc_bplist_writer_func_data(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream && object, tb_false); - - // writ - return tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_DATA, (tb_byte_t const*)tb_oc_data_getp(object), tb_oc_data_size(object), item_size); -} -static tb_bool_t tb_oc_bplist_writer_func_array(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream && object, tb_false); - - // index tables - tb_byte_t* index_tables = (tb_byte_t*)tb_object_getp(object); - - // size - tb_size_t size = tb_oc_array_size(object); - tb_assert_and_check_return_val(!size == !index_tables, tb_false); - - // writ flag - tb_uint8_t flag = TB_OBJECT_BPLIST_TYPE_ARRAY | (size < 15 ? (tb_uint8_t)size : 0xf); - if (!tb_stream_bwrit_u8(writer->stream, flag)) return tb_false; - - // writ size - if (size >= 15) - { - // init osize - tb_object_ref_t osize = tb_oc_bplist_writer_init_number(size); - tb_assert_and_check_return_val(osize, tb_false); - - // writ it - if (!tb_oc_bplist_writer_func_number(writer, osize, item_size)) - { - tb_object_exit(osize); - return tb_false; - } - - // exit osize - tb_object_exit(osize); - } - - // writ index tables - if (index_tables) - { - if (!tb_stream_bwrit(writer->stream, index_tables, size * item_size)) return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_bplist_writer_func_string(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream && object, tb_false); -#if 0 - // writ utf8 - return tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_STRING, tb_oc_string_cstr(object), tb_oc_string_size(object), item_size); -#else - // writ utf16 - tb_char_t const* utf8 = tb_oc_string_cstr(object); - tb_size_t size = tb_oc_string_size(object); - if (utf8 && size) - { -#ifdef TB_CONFIG_MODULE_HAVE_CHARSET - // done - tb_bool_t ok = tb_false; - tb_char_t* utf16 = tb_null; - tb_size_t osize = 0; - do - { - // init utf16 data - utf16 = tb_malloc_cstr((size + 1) << 2); - tb_assert_and_check_break(utf16); - - // utf8 to utf16 - osize = tb_charset_conv_data(TB_CHARSET_TYPE_UTF8, TB_CHARSET_TYPE_UTF16, (tb_byte_t const*)utf8, size, (tb_byte_t*)utf16, (size + 1) << 2); - tb_assert_and_check_break(osize > 0 && osize < (size + 1) << 2); - tb_assert_and_check_break(!(osize & 1)); - - // ok - ok = tb_true; - - } while (0); - - // ok? - if (ok) - { - // only ascii? writ utf8 - if (osize == (size << 1)) ok = tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_STRING, (tb_byte_t*)utf8, size, item_size); - // writ utf16 - else ok = tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_UNICODE, (tb_byte_t*)utf16, osize >> 1, item_size); - - } - - // exit utf16 - if (utf16) tb_free(utf16); - utf16 = tb_null; -#else - // writ utf8 only - tb_bool_t ok = tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_STRING, (tb_byte_t*)utf8, size, item_size); -#endif - - // ok? - return ok; - } - // writ empty - else return tb_oc_bplist_writer_func_rdata(writer, TB_OBJECT_BPLIST_TYPE_STRING, tb_null, 0, item_size); -#endif -} -static tb_bool_t tb_oc_bplist_writer_func_number(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream && object, tb_false); - - // done - switch (tb_oc_number_type(object)) - { - case TB_OC_NUMBER_TYPE_UINT64: - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 3)) return tb_false; - if (!tb_stream_bwrit_u64_be(writer->stream, tb_oc_number_uint64(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT64: - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 3)) return tb_false; - if (!tb_stream_bwrit_s64_be(writer->stream, tb_oc_number_sint64(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT32: - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 2)) return tb_false; - if (!tb_stream_bwrit_u32_be(writer->stream, tb_oc_number_uint32(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT32: - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 2)) return tb_false; - if (!tb_stream_bwrit_s32_be(writer->stream, tb_oc_number_sint32(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT16: - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 1)) return tb_false; - if (!tb_stream_bwrit_u16_be(writer->stream, tb_oc_number_uint16(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT16: - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT | 1)) return tb_false; - if (!tb_stream_bwrit_s16_be(writer->stream, tb_oc_number_sint16(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT8: - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT)) return tb_false; - if (!tb_stream_bwrit_u8(writer->stream, tb_oc_number_uint8(object))) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT8: - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_UINT)) return tb_false; - if (!tb_stream_bwrit_s8(writer->stream, tb_oc_number_sint8(object))) return tb_false; - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - { - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_REAL | 2)) return tb_false; - if (!tb_stream_bwrit_float_be(writer->stream, tb_oc_number_float(object))) return tb_false; - } - break; - case TB_OC_NUMBER_TYPE_DOUBLE: - { - if (!tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_REAL | 3)) return tb_false; - if (!tb_stream_bwrit_double_bbe(writer->stream, tb_oc_number_double(object))) return tb_false; - } - break; -#endif - default: - tb_assert_and_check_return_val(0, tb_false); - break; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_bplist_writer_func_boolean(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream && object, tb_false); - - // writ it - return tb_stream_bwrit_u8(writer->stream, TB_OBJECT_BPLIST_TYPE_NONE | (tb_oc_boolean_bool(object)? TB_OBJECT_BPLIST_TYPE_TRUE : TB_OBJECT_BPLIST_TYPE_FALSE)); -} -static tb_bool_t tb_oc_bplist_writer_func_dictionary(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream && object, tb_false); - - // index tables - tb_byte_t* index_tables = (tb_byte_t*)tb_object_getp(object); - - // size - tb_size_t size = tb_oc_dictionary_size(object); - tb_assert_and_check_return_val(!size == !index_tables, tb_false); - - // writ flag - tb_uint8_t flag = TB_OBJECT_BPLIST_TYPE_DICT | (size < 15 ? (tb_uint8_t)size : 0xf); - if (!tb_stream_bwrit_u8(writer->stream, flag)) return tb_false; - - // writ size - if (size >= 15) - { - // init osize - tb_object_ref_t osize = tb_oc_bplist_writer_init_number(size); - tb_assert_and_check_return_val(osize, tb_false); - - // writ it - if (!tb_oc_bplist_writer_func_number(writer, osize, item_size)) - { - tb_object_exit(osize); - return tb_false; - } - - // exit osize - tb_object_exit(osize); - } - - // writ index tables - if (index_tables) - { - if (!tb_stream_bwrit(writer->stream, index_tables, (size << 1) * item_size)) return tb_false; - } - - // ok - return tb_true; -} -static tb_uint64_t tb_oc_bplist_writer_builder_maxn(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object, 0); - - // walk - tb_uint64_t size = 0; - switch (tb_object_type(object)) - { - case TB_OBJECT_TYPE_ARRAY: - { - // walk - tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object)) - { - if (item) size += tb_oc_bplist_writer_builder_maxn(item); - } - } - break; - case TB_OBJECT_TYPE_DICTIONARY: - { - // walk - tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object)) - { - // item - if (item && item->key && item->val) - size += 1 + tb_oc_bplist_writer_builder_maxn(item->val); - } - } - break; - default: - break; - } - - return size + 1; -} -static tb_size_t tb_oc_bplist_writer_builder_addo(tb_object_ref_t object, tb_object_ref_t list, tb_hash_map_ref_t hash) -{ - // check - tb_assert_and_check_return_val(object && list && hash, 0); - - // the object index - tb_size_t index = (tb_size_t)tb_hash_map_get(hash, object); - - // new object? - if (!index) - { - // append object - tb_oc_array_append(list, object); - - // index - index = tb_oc_array_size(list); - - // set index - tb_hash_map_insert(hash, object, (tb_pointer_t)index); - tb_object_retain(object); - - // check - tb_assert(!tb_object_getp(object)); - } - - // ok? - return index; -} -static tb_void_t tb_oc_bplist_writer_builder_init(tb_object_ref_t object, tb_object_ref_t list, tb_hash_map_ref_t hash, tb_size_t item_size) -{ - // check - tb_assert_and_check_return(object && list && hash); - - // build items - switch (tb_object_type(object)) - { - case TB_OBJECT_TYPE_ARRAY: - { - // make index tables - tb_byte_t* index_tables = tb_null; - tb_size_t size = tb_oc_array_size(object); - if (size) - { - index_tables = (tb_byte_t*)tb_object_getp(object); - if (!index_tables) - { - // make it - index_tables = tb_malloc0_bytes(size * item_size); - - // FIXME: not using the user private data - tb_object_setp(object, index_tables); - } - } - - // walk - tb_size_t i = 0; - tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object)) - { - // build item - if (item) - { - // add item to builder - tb_size_t index = tb_oc_bplist_writer_builder_addo(item, list, hash); - - // add index to tables - if (index && index_tables) tb_oc_bplist_writer_bits_set(index_tables + i++ * item_size, index - 1, item_size); -// tb_trace_d("item: %p[%lu]", index_tables, index - 1); - - // init next - tb_oc_bplist_writer_builder_init(item, list, hash, item_size); - } - } - } - break; - case TB_OBJECT_TYPE_DICTIONARY: - { - // make index tables - tb_byte_t* index_tables = tb_null; - tb_size_t size = tb_oc_dictionary_size(object); - if (size) - { - index_tables = (tb_byte_t*)tb_object_getp(object); - if (!index_tables) - { - // make it - index_tables = tb_malloc0_bytes((size << 1) * item_size); - - // FIXME: not using the user private data - tb_object_setp(object, index_tables); - } - } - - // walk keys - { - tb_size_t i = 0; - tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object)) - { - // item - if (item && item->key && item->val) - { - // make key object - tb_object_ref_t key = tb_oc_string_init_from_cstr(item->key); - if (key) - { - // add key to builder - tb_size_t index = tb_oc_bplist_writer_builder_addo(key, list, hash); - - // add index to tables - if (index && index_tables) tb_oc_bplist_writer_bits_set(index_tables + i++ * item_size, index - 1, item_size); -// tb_trace_d("keys: %p[%lu]", index_tables, index - 1); - - // build key - tb_oc_bplist_writer_builder_init(key, list, hash, item_size); - tb_object_exit(key); - - } - } - } - } - - // walk vals - { - tb_size_t i = 0; - tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object)) - { - // item - if (item && item->key && item->val) - { - // add val to builder - tb_size_t index = tb_oc_bplist_writer_builder_addo(item->val, list, hash); - - // add index to tables - if (index && index_tables) tb_oc_bplist_writer_bits_set(index_tables + (size + i++) * item_size, index - 1, item_size); -// tb_trace_d("vals: %p[%lu]", index_tables, index - 1); - - // build val - tb_oc_bplist_writer_builder_init(item->val, list, hash, item_size); - } - } - } - } - break; - default: - break; - } -} -static tb_void_t tb_oc_bplist_writer_builder_exit(tb_object_ref_t list, tb_hash_map_ref_t hash) -{ - // exit hash - if (hash) - { - // walk - tb_for_all (tb_hash_map_item_ref_t, item, hash) - { - // exit item - if (item && item->name) - { - tb_byte_t* priv = (tb_byte_t*)tb_object_getp((tb_object_ref_t)item->name); - if (priv) - { - tb_free(priv); - tb_object_setp((tb_object_ref_t)item->name, tb_null); - } - - tb_object_exit((tb_object_ref_t)item->name); - } - } - - // exit it - tb_hash_map_exit(hash); - } - - // exit list - if (list) tb_object_exit(list); -} -static tb_long_t tb_oc_bplist_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate) -{ - // check - tb_assert_and_check_return_val(object && stream, -1); - - // done - tb_bool_t ok = tb_false; - tb_size_t i = 0; - tb_byte_t pad[6] = {0}; - tb_object_ref_t list = tb_null; - tb_hash_map_ref_t hash = tb_null; - tb_size_t object_count = 0; - tb_uint64_t object_maxn = 0; - tb_uint64_t root_object = 0; - tb_uint64_t offset_table_index = 0; - tb_size_t offset_size = 0; - tb_size_t item_size = 0; - tb_uint64_t* offsets = tb_null; - tb_hize_t bof = 0; - tb_hize_t eof = 0; - do - { - // init writer - tb_oc_bplist_writer_t writer = {0}; - writer.stream = stream; - - // init list - list = tb_oc_array_init(TB_OBJECT_BPLIST_LIST_GROW, tb_true); - tb_assert_and_check_break(list); - - // init hash - hash = tb_hash_map_init(0, tb_element_ptr(tb_null, tb_null), tb_element_uint32()); - tb_assert_and_check_break(hash); - - // object maxn - object_maxn = tb_oc_bplist_writer_builder_maxn(object); - item_size = tb_object_need_bytes(object_maxn); - tb_trace_d("object_maxn: %llu", object_maxn); - tb_trace_d("item_size: %lu", item_size); - - // add root object to builder - tb_oc_bplist_writer_builder_addo(object, list, hash); - - // init object builder - tb_oc_bplist_writer_builder_init(object, list, hash, item_size); - - // init object count - object_count = tb_oc_array_size(list); - tb_trace_d("object_count: %lu", object_count); - - // init offsets - offsets = (tb_uint64_t*)tb_malloc0(object_count * sizeof(tb_uint64_t)); - tb_assert_and_check_break(offsets); - - // the begin offset - bof = tb_stream_offset(stream); - - // writ magic & version - if (!tb_stream_bwrit(stream, (tb_byte_t const*)"bplist00", 8)) break; - - // writ objects - if (object_count) - { - i = 0; - tb_bool_t failed = tb_false; - tb_for_all_if (tb_object_ref_t, item, tb_oc_array_itor(list), item && !failed) - { - // check - tb_assert_and_check_break_state(i < object_count, failed, tb_true); - - // save offset - offsets[i++] = tb_stream_offset(stream); - - // the func - tb_oc_bplist_writer_func_t func = tb_oc_bplist_writer_func(tb_object_type(item)); - tb_assert_and_check_continue(func); - - // writ object - if (!func(&writer, item, item_size)) - { - failed = tb_true; - break; - } - } - - // failed? - tb_check_break(!failed); - } - - // offset table index - offset_table_index = tb_stream_offset(stream); - offset_size = tb_object_need_bytes(offset_table_index); - tb_trace_d("offset_table_index: %llu", offset_table_index); - tb_trace_d("offset_size: %lu", offset_size); - - // writ offset table - tb_bool_t failed = tb_false; - for (i = 0; !failed && i < object_count; i++) - { - switch (offset_size) - { - case 1: - if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)offsets[i])) failed = tb_true; - break; - case 2: - if (!tb_stream_bwrit_u16_be(stream, (tb_uint16_t)offsets[i])) failed = tb_true; - break; - case 4: - if (!tb_stream_bwrit_u32_be(stream, (tb_uint32_t)offsets[i])) failed = tb_true; - break; - case 8: - if (!tb_stream_bwrit_u64_be(stream, (tb_uint64_t)offsets[i])) failed = tb_true; - break; - default: - tb_assert_and_check_break_state(0, failed, tb_true); - break; - } - } - - // failed? - tb_check_break(!failed); - - // writ pad, like apple? - if (!tb_stream_bwrit(stream, pad, 6)) break; - - // writ tail - if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)offset_size)) break; - if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)item_size)) break; - if (!tb_stream_bwrit_u64_be(stream, object_count)) break; - if (!tb_stream_bwrit_u64_be(stream, root_object)) break; - if (!tb_stream_bwrit_u64_be(stream, offset_table_index)) break; - - // sync stream - if (!tb_stream_sync(stream, tb_true)) break; - - // the end offset - eof = tb_stream_offset(stream); - - // ok - ok = tb_true; - - } while (0); - - // exit offsets - if (offsets) tb_free(offsets); - offsets = tb_null; - - // exit object builder - tb_oc_bplist_writer_builder_exit(list, hash); - list = tb_null; - hash = tb_null; - - // ok? - return (ok && (eof >= bof))? (tb_long_t)(eof - bof) : -1; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_writer_t* tb_oc_bplist_writer() -{ - // the writer - static tb_oc_writer_t s_writer = {0}; - - // init writer - s_writer.writ = tb_oc_bplist_writer_done; - - // init hooker - s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_writer.hooker, tb_null); - - // hook writer - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_bplist_writer_func_date); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_bplist_writer_func_data); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_bplist_writer_func_array); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_bplist_writer_func_string); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_bplist_writer_func_number); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_bplist_writer_func_boolean); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_bplist_writer_func_dictionary); - - // ok - return &s_writer; -} -tb_bool_t tb_oc_bplist_writer_hook(tb_size_t type, tb_oc_bplist_writer_func_t func) -{ - // check - tb_assert_and_check_return_val(func, tb_false); - - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_BPLIST); - tb_assert_and_check_return_val(writer && writer->hooker, tb_false); - - // hook it - tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func); - - // ok - return tb_true; -} -tb_oc_bplist_writer_func_t tb_oc_bplist_writer_func(tb_size_t type) -{ - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_BPLIST); - tb_assert_and_check_return_val(writer && writer->hooker, tb_null); - - // the func - return (tb_oc_bplist_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/writer/bplist.h b/core/src/tbox/src/tbox/object/impl/writer/bplist.h deleted file mode 100644 index 83c316541..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/bplist.h +++ /dev/null @@ -1,87 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file bplist.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_WRITER_BPLIST_H -#define TB_OBJECT_IMPL_WRITER_BPLIST_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the object bplist writer type -typedef struct __tb_oc_bplist_writer_t -{ - /// the stream - tb_stream_ref_t stream; - -}tb_oc_bplist_writer_t; - -/// the bplist writer func type -typedef tb_bool_t (*tb_oc_bplist_writer_func_t)(tb_oc_bplist_writer_t* writer, tb_object_ref_t object, tb_size_t item_size); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the bplist object writer - * - * @return the bplist object writer - */ -tb_oc_writer_t* tb_oc_bplist_writer(tb_noarg_t); - -/*! hook the bplist writer - * - * @param type the object type - * @param func the writer func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_bplist_writer_hook(tb_size_t type, tb_oc_bplist_writer_func_t func); - -/*! the bplist writer func - * - * @param type the object type - * - * @return the object writer func - */ -tb_oc_bplist_writer_func_t tb_oc_bplist_writer_func(tb_size_t type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/writer/json.c b/core/src/tbox/src/tbox/object/impl/writer/json.c deleted file mode 100644 index 80f8b46e8..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/json.c +++ /dev/null @@ -1,331 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file json.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_writer_json" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "json.h" -#include "writer.h" -#include "../../../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_bool_t tb_oc_json_writer_func_null(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (tb_stream_printf(writer->stream, "null") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // ok - return tb_true; -} -static tb_bool_t tb_oc_json_writer_func_array(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (tb_oc_array_size(object)) - { - // writ beg - if (tb_stream_printf(writer->stream, "[") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // walk - tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object)) - { - // item - if (item) - { - // func - tb_oc_json_writer_func_t func = tb_oc_json_writer_func(item->type); - tb_assert_and_check_continue(func); - - // writ tab - if (item_itor != item_head) - { - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, ",") < 0) return tb_false; - if (!tb_oc_writer_tab(writer->stream, writer->deflate, 1)) return tb_false; - } - else if (!tb_oc_writer_tab(writer->stream, writer->deflate, level + 1)) return tb_false; - - // writ - if (!func(writer, item, level + 1)) return tb_false; - } - } - - // writ end - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "]") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - if (tb_stream_printf(writer->stream, "[]") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_json_writer_func_string(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (tb_oc_string_size(object)) - { - if (tb_stream_printf(writer->stream, "\"%s\"", tb_oc_string_cstr(object)) < 0) return tb_false; - } - else if (tb_stream_printf(writer->stream, "\"\"") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // ok - return tb_true; -} -static tb_bool_t tb_oc_json_writer_func_number(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - switch (tb_oc_number_type(object)) - { - case TB_OC_NUMBER_TYPE_UINT64: - if (tb_stream_printf(writer->stream, "%llu", tb_oc_number_uint64(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT64: - if (tb_stream_printf(writer->stream, "%lld", tb_oc_number_sint64(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT32: - if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint32(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT32: - if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint32(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT16: - if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint16(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT16: - if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint16(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT8: - if (tb_stream_printf(writer->stream, "%u", tb_oc_number_uint8(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT8: - if (tb_stream_printf(writer->stream, "%d", tb_oc_number_sint8(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - if (tb_stream_printf(writer->stream, "%f", tb_oc_number_float(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_DOUBLE: - if (tb_stream_printf(writer->stream, "%lf", tb_oc_number_double(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; -#endif - default: - break; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_json_writer_func_boolean(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (tb_stream_printf(writer->stream, "%s", tb_oc_boolean_bool(object)? "true" : "false") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // ok - return tb_true; -} -static tb_bool_t tb_oc_json_writer_func_dictionary(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (tb_oc_dictionary_size(object)) - { - // writ beg - if (tb_stream_printf(writer->stream, "{") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // walk - tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object)) - { - // item - if (item && item->key && item->val) - { - // func - tb_oc_json_writer_func_t func = tb_oc_json_writer_func(item->val->type); - tb_assert_and_check_continue(func); - - // writ tab - if (item_itor != item_head) - { - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, ",") < 0) return tb_false; - if (!tb_oc_writer_tab(writer->stream, writer->deflate, 1)) return tb_false; - } - else if (!tb_oc_writer_tab(writer->stream, writer->deflate, level + 1)) return tb_false; - - // writ key - if (tb_stream_printf(writer->stream, "\"%s\":", item->key) < 0) return tb_false; - - // writ spaces - if (!writer->deflate) if (tb_stream_printf(writer->stream, " ") < 0) return tb_false; - if (item->val->type == TB_OBJECT_TYPE_DICTIONARY || item->val->type == TB_OBJECT_TYPE_ARRAY) - { - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level + 1)) return tb_false; - } - - // writ val - if (!func(writer, item->val, level + 1)) return tb_false; - } - } - - // writ end - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "}") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - if (tb_stream_printf(writer->stream, "{}") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_long_t tb_oc_json_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate) -{ - // check - tb_assert_and_check_return_val(object && stream, -1); - - // init writer - tb_oc_json_writer_t writer = {0}; - writer.stream = stream; - writer.deflate = deflate; - - // func - tb_oc_json_writer_func_t func = tb_oc_json_writer_func(object->type); - tb_assert_and_check_return_val(func, tb_false); - - // the begin offset - tb_hize_t bof = tb_stream_offset(stream); - - // writ - if (!func(&writer, object, 0)) return -1; - - // sync - if (!tb_stream_sync(stream, tb_true)) return -1; - - // the end offset - tb_hize_t eof = tb_stream_offset(stream); - - // ok? - return eof >= bof? (tb_long_t)(eof - bof) : -1; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_writer_t* tb_oc_json_writer() -{ - // the writer - static tb_oc_writer_t s_writer = {0}; - - // init writer - s_writer.writ = tb_oc_json_writer_done; - - // init hooker - s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_writer.hooker, tb_null); - - // hook writer - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NULL, tb_oc_json_writer_func_null); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_json_writer_func_array); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_json_writer_func_string); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_json_writer_func_number); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_json_writer_func_boolean); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_json_writer_func_dictionary); - - // ok - return &s_writer; -} -tb_bool_t tb_oc_json_writer_hook(tb_size_t type, tb_oc_json_writer_func_t func) -{ - // check - tb_assert_and_check_return_val(func, tb_false); - - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_JSON); - tb_assert_and_check_return_val(writer && writer->hooker, tb_false); - - // hook it - tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func); - - // ok - return tb_true; -} -tb_oc_json_writer_func_t tb_oc_json_writer_func(tb_size_t type) -{ - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_JSON); - tb_assert_and_check_return_val(writer && writer->hooker, tb_null); - - // the func - return (tb_oc_json_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/writer/json.h b/core/src/tbox/src/tbox/object/impl/writer/json.h deleted file mode 100644 index 2abd7dd49..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/json.h +++ /dev/null @@ -1,90 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file json.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_WRITER_JSON_H -#define TB_OBJECT_IMPL_WRITER_JSON_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the object json writer type -typedef struct __tb_oc_json_writer_t -{ - /// the stream - tb_stream_ref_t stream; - - /// is deflate? - tb_bool_t deflate; - -}tb_oc_json_writer_t; - -/// the json writer func type -typedef tb_bool_t (*tb_oc_json_writer_func_t)(tb_oc_json_writer_t* writer, tb_object_ref_t object, tb_size_t level); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the json object writer - * - * @return the json object writer - */ -tb_oc_writer_t* tb_oc_json_writer(tb_noarg_t); - -/*! hook the json writer - * - * @param type the object type - * @param func the writer func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_json_writer_hook(tb_size_t type, tb_oc_json_writer_func_t func); - -/*! the json writer func - * - * @param type the object type - * - * @return the object writer func - */ -tb_oc_json_writer_func_t tb_oc_json_writer_func(tb_size_t type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/writer/prefix.h b/core/src/tbox/src/tbox/object/impl/writer/prefix.h deleted file mode 100644 index c383641cc..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/prefix.h +++ /dev/null @@ -1,114 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_WRITER_PREFIX_H -#define TB_OBJECT_WRITER_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * inlines - */ -static __tb_inline__ tb_bool_t tb_oc_writer_tab(tb_stream_ref_t stream, tb_bool_t deflate, tb_size_t tab) -{ - // writ tab - if (!deflate) - { - while (tab--) if (tb_stream_printf(stream, " ") < 0) return tb_false; - } - - // ok - return tb_true; -} -static __tb_inline__ tb_bool_t tb_oc_writer_newline(tb_stream_ref_t stream, tb_bool_t deflate) -{ - // writ newline - if (!deflate && tb_stream_printf(stream, __tb_newline__) < 0) return tb_false; - - // ok - return tb_true; -} -static __tb_inline__ tb_bool_t tb_oc_writer_bin_type_size(tb_stream_ref_t stream, tb_size_t type, tb_uint64_t size) -{ - // check - tb_assert_and_check_return_val(stream && type <= 0xff, tb_false); - - // byte for size < 64bits - tb_size_t sizeb = tb_object_need_bytes(size); - tb_assert_and_check_return_val(sizeb <= 8, tb_false); - - // flag for size - tb_size_t sizef = 0; - switch (sizeb) - { - case 1: sizef = 0xc; break; - case 2: sizef = 0xd; break; - case 4: sizef = 0xe; break; - case 8: sizef = 0xf; break; - default: break; - } - tb_assert_and_check_return_val(sizef, tb_false); - - // writ flag - tb_uint8_t flag = ((type < 0xf? (tb_uint8_t)type : 0xf) << 4) | (size < 0xc? (tb_uint8_t)size : (tb_uint8_t)sizef); - if (!tb_stream_bwrit_u8(stream, flag)) return tb_false; - - // trace -// tb_trace("writ: type: %lu, size: %llu", type, size); - - // writ type - if (type >= 0xf) if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)type)) return tb_false; - - // writ size - if (size >= 0xc) - { - switch (sizeb) - { - case 1: - if (!tb_stream_bwrit_u8(stream, (tb_uint8_t)size)) return tb_false; - break; - case 2: - if (!tb_stream_bwrit_u16_be(stream, (tb_uint16_t)size)) return tb_false; - break; - case 4: - if (!tb_stream_bwrit_u32_be(stream, (tb_uint32_t)size)) return tb_false; - break; - case 8: - if (!tb_stream_bwrit_u64_be(stream, (tb_uint64_t)size)) return tb_false; - break; - default: - tb_assert_and_check_return_val(0, tb_false); - break; - } - } - - // ok - return tb_true; -} - -#endif diff --git a/core/src/tbox/src/tbox/object/impl/writer/writer.c b/core/src/tbox/src/tbox/object/impl/writer/writer.c deleted file mode 100644 index f3e96a5c3..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/writer.c +++ /dev/null @@ -1,94 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file writer.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "writer.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * globals - */ - -// the object writer -static tb_oc_writer_t* g_writer[TB_OBJECT_FORMAT_MAXN] = {tb_null}; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_bool_t tb_oc_writer_set(tb_size_t format, tb_oc_writer_t* writer) -{ - // check - format &= 0x00ff; - tb_assert_and_check_return_val(writer && (format < tb_arrayn(g_writer)), tb_false); - - // exit the older writer if exists - tb_oc_writer_remove(format); - - // set - g_writer[format] = writer; - - // ok - return tb_true; -} -tb_void_t tb_oc_writer_remove(tb_size_t format) -{ - // check - format &= 0x00ff; - tb_assert_and_check_return((format < tb_arrayn(g_writer))); - - // exit it - if (g_writer[format]) - { - // exit hooker - if (g_writer[format]->hooker) tb_hash_map_exit(g_writer[format]->hooker); - g_writer[format]->hooker = tb_null; - - // clear it - g_writer[format] = tb_null; - } -} -tb_oc_writer_t* tb_oc_writer_get(tb_size_t format) -{ - // check - format &= 0x00ff; - tb_assert_and_check_return_val((format < tb_arrayn(g_writer)), tb_null); - - // ok - return g_writer[format]; -} -tb_long_t tb_oc_writer_done(tb_object_ref_t object, tb_stream_ref_t stream, tb_size_t format) -{ - // check - tb_assert_and_check_return_val(object && stream, -1); - - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(format); - tb_assert_and_check_return_val(writer && writer->writ, -1); - - // writ it - return writer->writ(stream, object, (format & TB_OBJECT_FORMAT_DEFLATE)? tb_true : tb_false); -} diff --git a/core/src/tbox/src/tbox/object/impl/writer/writer.h b/core/src/tbox/src/tbox/object/impl/writer/writer.h deleted file mode 100644 index 628297da9..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/writer.h +++ /dev/null @@ -1,86 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file writer.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_WRITER_H -#define TB_OBJECT_IMPL_WRITER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "xml.h" -#include "bin.h" -#include "json.h" -#include "xplist.h" -#include "bplist.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! set object writer - * - * @param format the writer format - * @param writer the writer - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_writer_set(tb_size_t format, tb_oc_writer_t* writer); - -/*! get object writer - * - * @param format the writer format - * - * @return the object writer - */ -tb_oc_writer_t* tb_oc_writer_get(tb_size_t format); - -/*! remove object writer - * - * @param format the writer format - */ -tb_void_t tb_oc_writer_remove(tb_size_t format); - -/*! done writer - * - * @param object the object - * @param stream the stream - * @param format the object format - * - * @return the writed size, failed: -1 - */ -tb_long_t tb_oc_writer_done(tb_object_ref_t object, tb_stream_ref_t stream, tb_size_t format); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - - -#endif diff --git a/core/src/tbox/src/tbox/object/impl/writer/xml.c b/core/src/tbox/src/tbox/object/impl/writer/xml.c deleted file mode 100644 index a75132d24..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/xml.c +++ /dev/null @@ -1,432 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file xml.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_writer_xml" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "xml.h" -#include "writer.h" -#include "../../../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_bool_t tb_oc_xml_writer_func_null(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<null/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xml_writer_func_date(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // no empty? - tb_time_t time = tb_oc_date_time(object); - if (time > 0) - { - // writ beg - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<date>") < 0) return tb_false; - - // writ date - tb_tm_t date = {0}; - if (tb_localtime(time, &date)) - { - if (tb_stream_printf(writer->stream, "%04ld-%02ld-%02ld %02ld:%02ld:%02ld" - , date.year - , date.month - , date.mday - , date.hour - , date.minute - , date.second) < 0) return tb_false; - } - - // writ end - if (tb_stream_printf(writer->stream, "</date>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - // writ - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<date/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xml_writer_func_data(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // no empty? - if (tb_oc_data_size(object)) - { - // writ beg - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<data>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // decode base64 data - tb_byte_t const* ib = (tb_byte_t const*)tb_oc_data_getp(object); - tb_size_t in = tb_oc_data_size(object); - tb_size_t on = in << 1; - tb_char_t* ob = tb_malloc0_cstr(on); - tb_assert_and_check_return_val(ob && on, tb_false); - on = tb_base64_encode(ib, in, ob, on); - tb_trace_d("base64: %u => %u", in, on); - - // writ data - tb_char_t const* p = ob; - tb_char_t const* e = ob + on; - tb_size_t n = 0; - for (; p < e && *p; p++, n++) - { - if (!(n & 63)) - { - if (n) if (!tb_oc_writer_newline(writer->stream, writer->deflate)) break; - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) break; - } - if (tb_stream_printf(writer->stream, "%c", *p) < 0) break; - } - - // free the data - tb_free(ob); - - // check - tb_check_return_val(p == e, tb_false); - - // writ newline - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // writ end - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "</data>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - // writ - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<data/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xml_writer_func_array(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (tb_oc_array_size(object)) - { - // writ beg - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<array>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // walk - tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object)) - { - // item - if (item) - { - // func - tb_oc_xml_writer_func_t func = tb_oc_xml_writer_func(item->type); - tb_assert_and_check_continue(func); - - // writ - if (!func(writer, item, level + 1)) return tb_false; - } - } - - // writ end - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "</array>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<array/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xml_writer_func_string(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_oc_string_size(object)) - { - if (tb_stream_printf(writer->stream, "<string>%s</string>", tb_oc_string_cstr(object)) < 0) return tb_false; - } - else if (tb_stream_printf(writer->stream, "<string/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xml_writer_func_number(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - switch (tb_oc_number_type(object)) - { - case TB_OC_NUMBER_TYPE_UINT64: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%llu</number>", tb_oc_number_uint64(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT64: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%lld</number>", tb_oc_number_sint64(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT32: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%u</number>", tb_oc_number_uint32(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT32: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%d</number>", tb_oc_number_sint32(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT16: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%u</number>", tb_oc_number_uint16(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT16: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%d</number>", tb_oc_number_sint16(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT8: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%u</number>", tb_oc_number_uint8(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT8: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%d</number>", tb_oc_number_sint8(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%f</number>", tb_oc_number_float(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_DOUBLE: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<number>%lf</number>", tb_oc_number_double(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; -#endif - default: - break; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xml_writer_func_boolean(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<%s/>", tb_oc_boolean_bool(object)? "true" : "false") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xml_writer_func_dictionary(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (tb_oc_dictionary_size(object)) - { - // writ beg - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<dict>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // walk - tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object)) - { - // item - if (item && item->key && item->val) - { - // func - tb_oc_xml_writer_func_t func = tb_oc_xml_writer_func(item->val->type); - tb_assert_and_check_continue(func); - - // writ key - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level + 1)) return tb_false; - if (tb_stream_printf(writer->stream, "<key>%s</key>", item->key) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // writ val - if (!func(writer, item->val, level + 1)) return tb_false; - } - } - - // writ end - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "</dict>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<dict/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_long_t tb_oc_xml_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate) -{ - // check - tb_assert_and_check_return_val(object && stream, -1); - - // init writer - tb_oc_xml_writer_t writer = {0}; - writer.stream = stream; - writer.deflate = deflate; - - // func - tb_oc_xml_writer_func_t func = tb_oc_xml_writer_func(object->type); - tb_assert_and_check_return_val(func, -1); - - // the begin offset - tb_hize_t bof = tb_stream_offset(stream); - - // writ xml header - if (tb_stream_printf(stream, "<?xml version=\"2.0\" encoding=\"utf-8\"?>") < 0) return -1; - if (!tb_oc_writer_newline(stream, deflate)) return -1; - - // writ - if (!func(&writer, object, 0)) return -1; - - // sync - if (!tb_stream_sync(stream, tb_true)) return -1; - - // the end offset - tb_hize_t eof = tb_stream_offset(stream); - - // ok? - return eof >= bof? (tb_long_t)(eof - bof) : -1; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_writer_t* tb_oc_xml_writer() -{ - // the writer - static tb_oc_writer_t s_writer = {0}; - - // init writer - s_writer.writ = tb_oc_xml_writer_done; - - // init hooker - s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_writer.hooker, tb_null); - - // hook writer - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NULL, tb_oc_xml_writer_func_null); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_xml_writer_func_date); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_xml_writer_func_data); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_xml_writer_func_array); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_xml_writer_func_string); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_xml_writer_func_number); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_xml_writer_func_boolean); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_xml_writer_func_dictionary); - - // ok - return &s_writer; -} -tb_bool_t tb_oc_xml_writer_hook(tb_size_t type, tb_oc_xml_writer_func_t func) -{ - // check - tb_assert_and_check_return_val(func, tb_false); - - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_XML); - tb_assert_and_check_return_val(writer && writer->hooker, tb_false); - - // hook it - tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func); - - // ok - return tb_true; -} -tb_oc_xml_writer_func_t tb_oc_xml_writer_func(tb_size_t type) -{ - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_XML); - tb_assert_and_check_return_val(writer && writer->hooker, tb_null); - - // the func - return (tb_oc_xml_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/writer/xml.h b/core/src/tbox/src/tbox/object/impl/writer/xml.h deleted file mode 100644 index 11fd3f703..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/xml.h +++ /dev/null @@ -1,90 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file xml.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_WRITER_XML_H -#define TB_OBJECT_IMPL_WRITER_XML_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the object xml writer type -typedef struct __tb_oc_xml_writer_t -{ - /// the stream - tb_stream_ref_t stream; - - /// is deflate? - tb_bool_t deflate; - -}tb_oc_xml_writer_t; - -/// the xml writer func type -typedef tb_bool_t (*tb_oc_xml_writer_func_t)(tb_oc_xml_writer_t* writer, tb_object_ref_t object, tb_size_t level); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the xml object writer - * - * @return the xml object writer - */ -tb_oc_writer_t* tb_oc_xml_writer(tb_noarg_t); - -/*! hook the xml writer - * - * @param type the object type - * @param func the writer func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_xml_writer_hook(tb_size_t type, tb_oc_xml_writer_func_t func); - -/*! the xml writer func - * - * @param type the object type - * - * @return the object writer func - */ -tb_oc_xml_writer_func_t tb_oc_xml_writer_func(tb_size_t type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/impl/writer/xplist.c b/core/src/tbox/src/tbox/object/impl/writer/xplist.c deleted file mode 100644 index bf02e8d9b..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/xplist.c +++ /dev/null @@ -1,425 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file xplist.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_writer_xplist" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "xplist.h" -#include "writer.h" -#include "../../../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_bool_t tb_oc_xplist_writer_func_date(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // no empty? - tb_time_t time = tb_oc_date_time(object); - if (time > 0) - { - // writ beg - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<date>") < 0) return tb_false; - - // writ date - tb_tm_t date = {0}; - if (tb_localtime(time, &date)) - { - if (tb_stream_printf(writer->stream, "%04ld-%02ld-%02ldT%02ld:%02ld:%02ldZ" - , date.year - , date.month - , date.mday - , date.hour - , date.minute - , date.second) < 0) return tb_false; - } - - // writ end - if (tb_stream_printf(writer->stream, "</date>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - // writ - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<date/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xplist_writer_func_data(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // no empty? - if (tb_oc_data_size(object)) - { - // writ beg - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<data>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // decode base64 data - tb_byte_t const* ib = (tb_byte_t const*)tb_oc_data_getp(object); - tb_size_t in = tb_oc_data_size(object); - tb_size_t on = in << 1; - tb_char_t* ob = tb_malloc0_cstr(on); - tb_assert_and_check_return_val(ob && on, tb_false); - on = tb_base64_encode(ib, in, ob, on); - tb_trace_d("base64: %u => %u", in, on); - - // writ data - tb_char_t const* p = ob; - tb_char_t const* e = ob + on; - tb_size_t n = 0; - for (; p < e && *p; p++, n++) - { - if (!(n % 68)) - { - if (n) if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - } - if (tb_stream_printf(writer->stream, "%c", *p) < 0) return tb_false; - } - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // free it - tb_free(ob); - - // writ end - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "</data>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - // writ - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<data>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "</data>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xplist_writer_func_array(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (tb_oc_array_size(object)) - { - // writ beg - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<array>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // walk - tb_for_all (tb_object_ref_t, item, tb_oc_array_itor(object)) - { - // item - if (item) - { - // func - tb_oc_xplist_writer_func_t func = tb_oc_xplist_writer_func(item->type); - tb_assert_and_check_continue(func); - - // writ - if (!func(writer, item, level + 1)) return tb_false; - } - } - - // writ end - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "</array>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<array/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xplist_writer_func_string(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_oc_string_size(object)) - { - if (tb_stream_printf(writer->stream, "<string>%s</string>", tb_oc_string_cstr(object)) < 0) return tb_false; - } - else if (tb_stream_printf(writer->stream, "<string/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xplist_writer_func_number(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - switch (tb_oc_number_type(object)) - { - case TB_OC_NUMBER_TYPE_UINT64: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<integer>%llu</integer>", tb_oc_number_uint64(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT64: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<integer>%lld</integer>", tb_oc_number_sint64(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT32: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<integer>%u</integer>", tb_oc_number_uint32(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT32: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<integer>%d</integer>", tb_oc_number_sint32(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT16: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<integer>%u</integer>", tb_oc_number_uint16(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT16: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<integer>%d</integer>", tb_oc_number_sint16(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_UINT8: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<integer>%u</integer>", tb_oc_number_uint8(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_SINT8: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<integer>%d</integer>", tb_oc_number_sint8(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<real>%f</real>", tb_oc_number_float(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; - case TB_OC_NUMBER_TYPE_DOUBLE: - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<real>%lf</real>", tb_oc_number_double(object)) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - break; -#endif - default: - break; - } - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xplist_writer_func_boolean(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<%s/>", tb_oc_boolean_bool(object)? "true" : "false") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // ok - return tb_true; -} -static tb_bool_t tb_oc_xplist_writer_func_dictionary(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level) -{ - // check - tb_assert_and_check_return_val(writer && writer->stream, tb_false); - - // writ - if (tb_oc_dictionary_size(object)) - { - // writ beg - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<dict>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // walk - tb_for_all (tb_oc_dictionary_item_t*, item, tb_oc_dictionary_itor(object)) - { - // item - if (item && item->key && item->val) - { - // func - tb_oc_xplist_writer_func_t func = tb_oc_xplist_writer_func(item->val->type); - tb_assert_and_check_continue(func); - - // writ key - tb_oc_writer_tab(writer->stream, writer->deflate, level + 1); - if (tb_stream_printf(writer->stream, "<key>%s</key>", item->key) < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - - // writ val - if (!func(writer, item->val, level + 1)) return tb_false; - } - } - - // writ end - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "</dict>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - else - { - if (!tb_oc_writer_tab(writer->stream, writer->deflate, level)) return tb_false; - if (tb_stream_printf(writer->stream, "<dict/>") < 0) return tb_false; - if (!tb_oc_writer_newline(writer->stream, writer->deflate)) return tb_false; - } - - // ok - return tb_true; -} -static tb_long_t tb_oc_xplist_writer_done(tb_stream_ref_t stream, tb_object_ref_t object, tb_bool_t deflate) -{ - // check - tb_assert_and_check_return_val(object && stream, -1); - - // init writer - tb_oc_xplist_writer_t writer = {0}; - writer.stream = stream; - writer.deflate = deflate; - - // func - tb_oc_xplist_writer_func_t func = tb_oc_xplist_writer_func(object->type); - tb_assert_and_check_return_val(func, -1); - - // the begin offset - tb_hize_t bof = tb_stream_offset(stream); - - // writ xplist header - if (tb_stream_printf(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>") < 0) return -1; - if (!tb_oc_writer_newline(stream, deflate)) return -1; - if (tb_stream_printf(stream, "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">") < 0) return -1; - if (!tb_oc_writer_newline(stream, deflate)) return -1; - if (tb_stream_printf(stream, "<plist version=\"1.0\">") < 0) return -1; - if (!tb_oc_writer_newline(stream, deflate)) return -1; - - // writ - if (!func(&writer, object, 0)) return -1; - - // writ xplist end - if (tb_stream_printf(stream, "</plist>") < 0) return -1; - if (!tb_oc_writer_newline(stream, deflate)) return -1; - - // sync - if (!tb_stream_sync(stream, tb_true)) return -1; - - // the end offset - tb_hize_t eof = tb_stream_offset(stream); - - // ok? - return eof >= bof? (tb_long_t)(eof - bof) : -1; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_oc_writer_t* tb_oc_xplist_writer() -{ - // the writer - static tb_oc_writer_t s_writer = {0}; - - // init writer - s_writer.writ = tb_oc_xplist_writer_done; - - // init hooker - s_writer.hooker = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_uint32(), tb_element_ptr(tb_null, tb_null)); - tb_assert_and_check_return_val(s_writer.hooker, tb_null); - - // hook writer - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATE, tb_oc_xplist_writer_func_date); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DATA, tb_oc_xplist_writer_func_data); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_ARRAY, tb_oc_xplist_writer_func_array); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_STRING, tb_oc_xplist_writer_func_string); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_NUMBER, tb_oc_xplist_writer_func_number); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_BOOLEAN, tb_oc_xplist_writer_func_boolean); - tb_hash_map_insert(s_writer.hooker, (tb_pointer_t)TB_OBJECT_TYPE_DICTIONARY, tb_oc_xplist_writer_func_dictionary); - - // ok - return &s_writer; -} -tb_bool_t tb_oc_xplist_writer_hook(tb_size_t type, tb_oc_xplist_writer_func_t func) -{ - // check - tb_assert_and_check_return_val(func, tb_false); - - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_XPLIST); - tb_assert_and_check_return_val(writer && writer->hooker, tb_false); - - // hook it - tb_hash_map_insert(writer->hooker, (tb_pointer_t)type, func); - - // ok - return tb_true; -} -tb_oc_xplist_writer_func_t tb_oc_xplist_writer_func(tb_size_t type) -{ - // the writer - tb_oc_writer_t* writer = tb_oc_writer_get(TB_OBJECT_FORMAT_XPLIST); - tb_assert_and_check_return_val(writer && writer->hooker, tb_null); - - // the func - return (tb_oc_xplist_writer_func_t)tb_hash_map_get(writer->hooker, (tb_pointer_t)type); -} - diff --git a/core/src/tbox/src/tbox/object/impl/writer/xplist.h b/core/src/tbox/src/tbox/object/impl/writer/xplist.h deleted file mode 100644 index decf74ec3..000000000 --- a/core/src/tbox/src/tbox/object/impl/writer/xplist.h +++ /dev/null @@ -1,90 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file xplist.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_IMPL_WRITER_XPLIST_H -#define TB_OBJECT_IMPL_WRITER_XPLIST_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the object xplist writer type -typedef struct __tb_oc_xplist_writer_t -{ - /// the stream - tb_stream_ref_t stream; - - /// is deflate? - tb_bool_t deflate; - -}tb_oc_xplist_writer_t; - -/// the xplist writer func type -typedef tb_bool_t (*tb_oc_xplist_writer_func_t)(tb_oc_xplist_writer_t* writer, tb_object_ref_t object, tb_size_t level); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! the xplist object writer - * - * @return the xplist object writer - */ -tb_oc_writer_t* tb_oc_xplist_writer(tb_noarg_t); - -/*! hook the xplist writer - * - * @param type the object type - * @param func the writer func - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_xplist_writer_hook(tb_size_t type, tb_oc_xplist_writer_func_t func); - -/*! the xplist writer func - * - * @param type the object type - * - * @return the object writer func - */ -tb_oc_xplist_writer_func_t tb_oc_xplist_writer_func(tb_size_t type); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/null.c b/core/src/tbox/src/tbox/object/null.c deleted file mode 100644 index 7a3c1fa31..000000000 --- a/core/src/tbox/src/tbox/object/null.c +++ /dev/null @@ -1,70 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file null.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_null" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static tb_object_ref_t tb_oc_null_copy(tb_object_ref_t object) -{ - return object; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * globals - */ - -// null -static tb_object_t const g_null = -{ - TB_OBJECT_FLAG_READONLY | TB_OBJECT_FLAG_SINGLETON -, TB_OBJECT_TYPE_NULL -, 1 -, tb_null -, tb_oc_null_copy -, tb_null -, tb_null - -}; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_object_ref_t tb_oc_null_init() -{ - return (tb_object_ref_t)&g_null; -} - diff --git a/core/src/tbox/src/tbox/object/null.h b/core/src/tbox/src/tbox/object/null.h deleted file mode 100644 index c9c066f3b..000000000 --- a/core/src/tbox/src/tbox/object/null.h +++ /dev/null @@ -1,55 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file null.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_NULL_H -#define TB_OBJECT_NULL_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init null - * - * @return the null object - */ -tb_object_ref_t tb_oc_null_init(tb_noarg_t); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/number.c b/core/src/tbox/src/tbox/object/number.c deleted file mode 100644 index 5dbcd4e90..000000000 --- a/core/src/tbox/src/tbox/object/number.c +++ /dev/null @@ -1,683 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file number.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_number" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the number type -typedef struct __tb_oc_number_t -{ - // the object base - tb_object_t base; - - // the number type - tb_size_t type; - - // the number value - union - { - // the uint8 - tb_uint8_t u8; - - // the sint8 - tb_sint8_t s8; - - // the uint16 - tb_uint16_t u16; - - // the sint16 - tb_sint16_t s16; - - // the uint32 - tb_uint32_t u32; - - // the sint32 - tb_sint32_t s32; - - // the uint64 - tb_uint64_t u64; - - // the sint64 - tb_sint64_t s64; - -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - // the float - tb_float_t f; - - // the double - tb_double_t d; -#endif - - }v; - -}tb_oc_number_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_oc_number_t* tb_oc_number_cast(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_NUMBER, tb_null); - - // cast - return (tb_oc_number_t*)object; -} -static tb_object_ref_t tb_oc_number_copy(tb_object_ref_t object) -{ - // check - tb_oc_number_t* number = (tb_oc_number_t*)object; - tb_assert_and_check_return_val(number, tb_null); - - // copy - switch (number->type) - { - case TB_OC_NUMBER_TYPE_UINT64: - return tb_oc_number_init_from_uint64(number->v.u64); - case TB_OC_NUMBER_TYPE_SINT64: - return tb_oc_number_init_from_sint64(number->v.s64); - case TB_OC_NUMBER_TYPE_UINT32: - return tb_oc_number_init_from_uint32(number->v.u32); - case TB_OC_NUMBER_TYPE_SINT32: - return tb_oc_number_init_from_sint32(number->v.s32); - case TB_OC_NUMBER_TYPE_UINT16: - return tb_oc_number_init_from_uint16(number->v.u16); - case TB_OC_NUMBER_TYPE_SINT16: - return tb_oc_number_init_from_sint16(number->v.s16); - case TB_OC_NUMBER_TYPE_UINT8: - return tb_oc_number_init_from_uint8(number->v.u8); - case TB_OC_NUMBER_TYPE_SINT8: - return tb_oc_number_init_from_sint8(number->v.s8); -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - return tb_oc_number_init_from_float(number->v.f); - case TB_OC_NUMBER_TYPE_DOUBLE: - return tb_oc_number_init_from_double(number->v.d); -#endif - default: - break; - } - - return tb_null; -} -static tb_void_t tb_oc_number_exit(tb_object_ref_t object) -{ - if (object) tb_free(object); -} -static tb_void_t tb_oc_number_clear(tb_object_ref_t object) -{ - // check - tb_oc_number_t* number = (tb_oc_number_t*)object; - tb_assert_and_check_return(number); - - // clear - switch (number->type) - { - case TB_OC_NUMBER_TYPE_UINT64: - number->v.u64 = 0; - break; - case TB_OC_NUMBER_TYPE_SINT64: - number->v.s64 = 0; - break; - case TB_OC_NUMBER_TYPE_UINT32: - number->v.u32 = 0; - break; - case TB_OC_NUMBER_TYPE_SINT32: - number->v.s32 = 0; - break; - case TB_OC_NUMBER_TYPE_UINT16: - number->v.u16 = 0; - break; - case TB_OC_NUMBER_TYPE_SINT16: - number->v.s16 = 0; - break; - case TB_OC_NUMBER_TYPE_UINT8: - number->v.u8 = 0; - break; - case TB_OC_NUMBER_TYPE_SINT8: - number->v.s8 = 0; - break; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - number->v.f = 0.; - break; - case TB_OC_NUMBER_TYPE_DOUBLE: - number->v.d = 0.; - break; -#endif - default: - break; - } -} -static tb_oc_number_t* tb_oc_number_init_base() -{ - // done - tb_bool_t ok = tb_false; - tb_oc_number_t* number = tb_null; - do - { - // make number - number = tb_malloc0_type(tb_oc_number_t); - tb_assert_and_check_break(number); - - // init number - if (!tb_object_init((tb_object_ref_t)number, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_NUMBER)) break; - - // init base - number->base.copy = tb_oc_number_copy; - number->base.exit = tb_oc_number_exit; - number->base.clear = tb_oc_number_clear; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (number) tb_object_exit((tb_object_ref_t)number); - number = tb_null; - } - - // ok? - return number; -} -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_object_ref_t tb_oc_number_init_from_uint8(tb_uint8_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_UINT8; - number->v.u8 = value; - - // ok - return (tb_object_ref_t)number; -} - -tb_object_ref_t tb_oc_number_init_from_sint8(tb_sint8_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_SINT8; - number->v.s8 = value; - - // ok - return (tb_object_ref_t)number; -} - -tb_object_ref_t tb_oc_number_init_from_uint16(tb_uint16_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_UINT16; - number->v.u16 = value; - - // ok - return (tb_object_ref_t)number; -} - -tb_object_ref_t tb_oc_number_init_from_sint16(tb_sint16_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_SINT16; - number->v.s16 = value; - - // ok - return (tb_object_ref_t)number; -} - -tb_object_ref_t tb_oc_number_init_from_uint32(tb_uint32_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_UINT32; - number->v.u32 = value; - - // ok - return (tb_object_ref_t)number; -} - -tb_object_ref_t tb_oc_number_init_from_sint32(tb_sint32_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_SINT32; - number->v.s32 = value; - - // ok - return (tb_object_ref_t)number; -} - -tb_object_ref_t tb_oc_number_init_from_uint64(tb_uint64_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_UINT64; - number->v.u64 = value; - - // ok - return (tb_object_ref_t)number; -} - -tb_object_ref_t tb_oc_number_init_from_sint64(tb_sint64_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_SINT64; - number->v.s64 = value; - - // ok - return (tb_object_ref_t)number; -} - -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -tb_object_ref_t tb_oc_number_init_from_float(tb_float_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_FLOAT; - number->v.f = value; - - // ok - return (tb_object_ref_t)number; -} - -tb_object_ref_t tb_oc_number_init_from_double(tb_double_t value) -{ - // make - tb_oc_number_t* number = tb_oc_number_init_base(); - tb_assert_and_check_return_val(number, tb_null); - - // init value - number->type = TB_OC_NUMBER_TYPE_DOUBLE; - number->v.d = value; - - // ok - return (tb_object_ref_t)number; -} -#endif - -tb_size_t tb_oc_number_type(tb_object_ref_t object) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, TB_OC_NUMBER_TYPE_NONE); - - // type - return number->type; -} - -tb_uint8_t tb_oc_number_uint8(tb_object_ref_t object) -{ - return (tb_uint8_t)tb_oc_number_uint64(object); -} -tb_sint8_t tb_oc_number_sint8(tb_object_ref_t object) -{ - return (tb_sint8_t)tb_oc_number_sint64(object); -} -tb_uint16_t tb_oc_number_uint16(tb_object_ref_t object) -{ - return (tb_uint16_t)tb_oc_number_uint64(object); -} -tb_sint16_t tb_oc_number_sint16(tb_object_ref_t object) -{ - return (tb_sint16_t)tb_oc_number_sint64(object); -} -tb_uint32_t tb_oc_number_uint32(tb_object_ref_t object) -{ - return (tb_uint32_t)tb_oc_number_uint64(object); -} -tb_sint32_t tb_oc_number_sint32(tb_object_ref_t object) -{ - return (tb_sint32_t)tb_oc_number_sint64(object); -} -tb_uint64_t tb_oc_number_uint64(tb_object_ref_t object) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, 0); - - // uint64 - switch (number->type) - { - case TB_OC_NUMBER_TYPE_UINT64: - return number->v.u64; - case TB_OC_NUMBER_TYPE_SINT64: - return number->v.s64; - case TB_OC_NUMBER_TYPE_UINT32: - return number->v.u32; - case TB_OC_NUMBER_TYPE_SINT32: - return number->v.s32; - case TB_OC_NUMBER_TYPE_UINT16: - return number->v.u16; - case TB_OC_NUMBER_TYPE_SINT16: - return number->v.s16; - case TB_OC_NUMBER_TYPE_UINT8: - return number->v.u8; - case TB_OC_NUMBER_TYPE_SINT8: - return number->v.s8; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - return (tb_uint64_t)number->v.f; - case TB_OC_NUMBER_TYPE_DOUBLE: - return (tb_uint64_t)number->v.d; -#endif - default: - break; - } - - tb_assert(0); - return 0; -} - -tb_sint64_t tb_oc_number_sint64(tb_object_ref_t object) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, 0); - - // sint64 - switch (number->type) - { - case TB_OC_NUMBER_TYPE_UINT64: - return number->v.u64; - case TB_OC_NUMBER_TYPE_SINT64: - return number->v.s64; - case TB_OC_NUMBER_TYPE_UINT32: - return number->v.u32; - case TB_OC_NUMBER_TYPE_SINT32: - return number->v.s32; - case TB_OC_NUMBER_TYPE_UINT16: - return number->v.u16; - case TB_OC_NUMBER_TYPE_SINT16: - return number->v.s16; - case TB_OC_NUMBER_TYPE_UINT8: - return number->v.u8; - case TB_OC_NUMBER_TYPE_SINT8: - return number->v.s8; -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT - case TB_OC_NUMBER_TYPE_FLOAT: - return (tb_sint64_t)number->v.f; - case TB_OC_NUMBER_TYPE_DOUBLE: - return (tb_sint64_t)number->v.d; -#endif - default: - break; - } - - tb_assert(0); - return 0; -} -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -tb_float_t tb_oc_number_float(tb_object_ref_t object) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, 0); - - // float - switch (number->type) - { - case TB_OC_NUMBER_TYPE_FLOAT: - return number->v.f; - case TB_OC_NUMBER_TYPE_DOUBLE: - return (tb_float_t)number->v.d; - case TB_OC_NUMBER_TYPE_UINT8: - return (tb_float_t)number->v.u8; - case TB_OC_NUMBER_TYPE_SINT8: - return (tb_float_t)number->v.s8; - case TB_OC_NUMBER_TYPE_UINT16: - return (tb_float_t)number->v.u16; - case TB_OC_NUMBER_TYPE_SINT16: - return (tb_float_t)number->v.s16; - case TB_OC_NUMBER_TYPE_UINT32: - return (tb_float_t)number->v.u32; - case TB_OC_NUMBER_TYPE_SINT32: - return (tb_float_t)number->v.s32; - case TB_OC_NUMBER_TYPE_UINT64: - return (tb_float_t)number->v.u64; - case TB_OC_NUMBER_TYPE_SINT64: - return (tb_float_t)number->v.s64; - default: - break; - } - - tb_assert(0); - return 0; -} -tb_double_t tb_oc_number_double(tb_object_ref_t object) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, 0); - - // double - switch (number->type) - { - case TB_OC_NUMBER_TYPE_DOUBLE: - return number->v.d; - case TB_OC_NUMBER_TYPE_FLOAT: - return (tb_double_t)number->v.f; - case TB_OC_NUMBER_TYPE_UINT8: - return (tb_double_t)number->v.u8; - case TB_OC_NUMBER_TYPE_SINT8: - return (tb_double_t)number->v.s8; - case TB_OC_NUMBER_TYPE_UINT16: - return (tb_double_t)number->v.u16; - case TB_OC_NUMBER_TYPE_SINT16: - return (tb_double_t)number->v.s16; - case TB_OC_NUMBER_TYPE_UINT32: - return (tb_double_t)number->v.u32; - case TB_OC_NUMBER_TYPE_SINT32: - return (tb_double_t)number->v.s32; - case TB_OC_NUMBER_TYPE_UINT64: - return (tb_double_t)number->v.u64; - case TB_OC_NUMBER_TYPE_SINT64: - return (tb_double_t)number->v.s64; - default: - break; - } - - tb_assert(0); - return 0; -} -#endif -tb_bool_t tb_oc_number_uint8_set(tb_object_ref_t object, tb_uint8_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_UINT8; - number->v.u8 = value; - - // ok - return tb_true; -} -tb_bool_t tb_oc_number_sint8_set(tb_object_ref_t object, tb_sint8_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_SINT8; - number->v.s8 = value; - - // ok - return tb_true; -} -tb_bool_t tb_oc_number_uint16_set(tb_object_ref_t object, tb_uint16_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_UINT16; - number->v.u16 = value; - - // ok - return tb_true; -} -tb_bool_t tb_oc_number_sint16_set(tb_object_ref_t object, tb_sint16_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_SINT16; - number->v.s16 = value; - - // ok - return tb_true; -} -tb_bool_t tb_oc_number_uint32_set(tb_object_ref_t object, tb_uint32_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_UINT32; - number->v.u32 = value; - - // ok - return tb_true; -} -tb_bool_t tb_oc_number_sint32_set(tb_object_ref_t object, tb_sint32_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_SINT32; - number->v.s32 = value; - - // ok - return tb_true; -} -tb_bool_t tb_oc_number_uint64_set(tb_object_ref_t object, tb_uint64_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_UINT64; - number->v.u64 = value; - - // ok - return tb_true; -} -tb_bool_t tb_oc_number_sint64_set(tb_object_ref_t object, tb_sint64_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_SINT64; - number->v.s64 = value; - - // ok - return tb_true; -} -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -tb_bool_t tb_oc_number_float_set(tb_object_ref_t object, tb_float_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_FLOAT; - number->v.f = value; - - // ok - return tb_true; -} -tb_bool_t tb_oc_number_double_set(tb_object_ref_t object, tb_double_t value) -{ - // check - tb_oc_number_t* number = tb_oc_number_cast(object); - tb_assert_and_check_return_val(number, tb_false); - - // init value - number->type = TB_OC_NUMBER_TYPE_DOUBLE; - number->v.d = value; - - // ok - return tb_true; -} -#endif diff --git a/core/src/tbox/src/tbox/object/number.h b/core/src/tbox/src/tbox/object/number.h deleted file mode 100644 index d518906cf..000000000 --- a/core/src/tbox/src/tbox/object/number.h +++ /dev/null @@ -1,334 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file number.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_NUMBER_H -#define TB_OBJECT_NUMBER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the number type enum -typedef enum __tb_oc_number_type_e -{ - TB_OC_NUMBER_TYPE_NONE = 0 -, TB_OC_NUMBER_TYPE_UINT8 = 1 -, TB_OC_NUMBER_TYPE_SINT8 = 2 -, TB_OC_NUMBER_TYPE_UINT16 = 3 -, TB_OC_NUMBER_TYPE_SINT16 = 4 -, TB_OC_NUMBER_TYPE_UINT32 = 5 -, TB_OC_NUMBER_TYPE_SINT32 = 6 -, TB_OC_NUMBER_TYPE_UINT64 = 7 -, TB_OC_NUMBER_TYPE_SINT64 = 8 -, TB_OC_NUMBER_TYPE_FLOAT = 9 -, TB_OC_NUMBER_TYPE_DOUBLE = 10 - -}tb_oc_number_type_e; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init number from uint8 - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_uint8(tb_uint8_t value); - -/*! init number from sint8 - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_sint8(tb_sint8_t value); - -/*! init number from uint16 - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_uint16(tb_uint16_t value); - -/*! init number from sint16 - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_sint16(tb_sint16_t value); - -/*! init number from uint32 - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_uint32(tb_uint32_t value); - -/*! init number from sint32 - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_sint32(tb_sint32_t value); - -/*! init number from uint64 - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_uint64(tb_uint64_t value); - -/*! init number from sint64 - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_sint64(tb_sint64_t value); - -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -/*! init number from float - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_float(tb_float_t value); - -/*! init number from double - * - * @param value the value - * - * @return the number object - */ -tb_object_ref_t tb_oc_number_init_from_double(tb_double_t value); -#endif - -/*! the number type - * - * @param object the object pointer - * - * @return the number type - */ -tb_size_t tb_oc_number_type(tb_object_ref_t number); - -/*! the uint8 value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_uint8_t tb_oc_number_uint8(tb_object_ref_t number); - -/*! the sint8 value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_sint8_t tb_oc_number_sint8(tb_object_ref_t number); - -/*! the uint16 value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_uint16_t tb_oc_number_uint16(tb_object_ref_t number); - -/*! the sint16 value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_sint16_t tb_oc_number_sint16(tb_object_ref_t number); - -/*! the uint32 value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_uint32_t tb_oc_number_uint32(tb_object_ref_t number); - -/*! the sint32 value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_sint32_t tb_oc_number_sint32(tb_object_ref_t number); - -/*! the uint64 value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_uint64_t tb_oc_number_uint64(tb_object_ref_t number); - -/*! the sint64 value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_sint64_t tb_oc_number_sint64(tb_object_ref_t number); - -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -/*! the float value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_float_t tb_oc_number_float(tb_object_ref_t number); - -/*! the double value of the number - * - * @param object the object pointer - * - * @return the number value - */ -tb_double_t tb_oc_number_double(tb_object_ref_t number); -#endif - -/*! set the uint8 value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_uint8_set(tb_object_ref_t number, tb_uint8_t value); - -/*! set the sint8 value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_sint8_set(tb_object_ref_t number, tb_sint8_t value); - -/*! set the uint16 value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_uint16_set(tb_object_ref_t number, tb_uint16_t value); - -/*! set the sint16 value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_sint16_set(tb_object_ref_t number, tb_sint16_t value); - -/*! set the uint32 value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_uint32_set(tb_object_ref_t number, tb_uint32_t value); - -/*! set the sint32 value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_sint32_set(tb_object_ref_t number, tb_sint32_t value); - -/*! set the uint64 value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_uint64_set(tb_object_ref_t number, tb_uint64_t value); - -/*! set the sint64 value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_sint64_set(tb_object_ref_t number, tb_sint64_t value); - -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -/*! set the float value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_float_set(tb_object_ref_t number, tb_float_t value); - -/*! set the double value - * - * @param object the object pointer - * @param value the number value - * - * @return tb_true or tb_false - */ -tb_bool_t tb_oc_number_double_set(tb_object_ref_t number, tb_double_t value); -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/object.c b/core/src/tbox/src/tbox/object/object.c deleted file mode 100644 index b92c0c4b2..000000000 --- a/core/src/tbox/src/tbox/object/object.c +++ /dev/null @@ -1,405 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file object.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "object" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" -#include "impl/impl.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_bool_t tb_object_init(tb_object_ref_t object, tb_size_t flag, tb_size_t type) -{ - // check - tb_assert_and_check_return_val(object, tb_false); - - // init - tb_memset(object, 0, sizeof(tb_object_t)); - object->flag = (tb_uint8_t)flag; - object->type = (tb_uint16_t)type; - object->refn = 1; - - // ok - return tb_true; -} -tb_void_t tb_object_exit(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return(object); - - // readonly? - tb_check_return(!(object->flag & TB_OBJECT_FLAG_READONLY)); - - // check refn - tb_assert_and_check_return(object->refn); - - // refn-- - object->refn--; - - // exit it? - if (!object->refn && object->exit) object->exit(object); -} -tb_void_t tb_object_clear(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return(object); - - // readonly? - tb_check_return(!(object->flag & TB_OBJECT_FLAG_READONLY)); - - // clear - if (object->clear) object->clear(object); -} -tb_void_t tb_object_setp(tb_object_ref_t object, tb_cpointer_t priv) -{ - // check - tb_assert_and_check_return(object); - - // set it - object->priv = priv; -} -tb_cpointer_t tb_object_getp(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object, tb_null); - - // get it - return object->priv; -} -tb_object_ref_t tb_object_copy(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && object->copy, tb_null); - - // copy - return object->copy(object); -} -tb_size_t tb_object_type(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object, TB_OBJECT_TYPE_NONE); - - // the object type - return object->type; -} -tb_object_ref_t tb_object_data(tb_object_ref_t object, tb_size_t format) -{ - // check - tb_assert_and_check_return_val(object, tb_null); - - // done - tb_object_ref_t odata = tb_null; - tb_size_t maxn = TB_STREAM_BLOCK_MAXN; - tb_byte_t* data = tb_null; - do - { - // make data - data = data? (tb_byte_t*)tb_ralloc(data, maxn) : tb_malloc_bytes(maxn); - tb_assert_and_check_break(data); - - // writ object to data - tb_long_t size = tb_object_writ_to_data(object, data, maxn, format); - - // ok? make the data object - if (size >= 0) odata = tb_oc_data_init_from_data(data, size); - // failed? grow it - else maxn <<= 1; - - } while (!odata); - - // exit data - if (data) tb_free(data); - data = tb_null; - - // ok? - return odata; -} -tb_object_ref_t tb_object_seek(tb_object_ref_t object, tb_char_t const* path, tb_bool_t bmacro) -{ - // check - tb_assert_and_check_return_val(object, tb_null); - - // null? - tb_check_return_val(path, object); - - // done - tb_object_ref_t root = object; - tb_char_t const* p = path; - tb_char_t const* e = path + tb_strlen(path); - while (p < e && object) - { - // done seek - switch (*p) - { - case '.': - { - // check - tb_assert_and_check_return_val(tb_object_type(object) == TB_OBJECT_TYPE_DICTIONARY, tb_null); - - // skip - p++; - - // read the key name - tb_char_t key[4096] = {0}; - tb_char_t* kb = key; - tb_char_t* ke = key + 4095; - for (; p < e && kb < ke && *p && (*p != '.' && *p != '[' && *p != ']'); p++, kb++) - { - if (*p == '\\') p++; - *kb = *p; - } - - // trace - tb_trace_d("key: %s", key); - - // the value - object = tb_oc_dictionary_value(object, key); - } - break; - case '[': - { - // check - tb_assert_and_check_return_val(tb_object_type(object) == TB_OBJECT_TYPE_ARRAY, tb_null); - - // skip - p++; - - // read the item index - tb_char_t index[32] = {0}; - tb_char_t* ib = index; - tb_char_t* ie = index + 31; - for (; p < e && ib < ie && *p && tb_isdigit10(*p); p++, ib++) *ib = *p; - - // trace - tb_trace_d("index: %s", index); - - // check - tb_size_t i = tb_atoi(index); - tb_assert_and_check_return_val(i < tb_oc_array_size(object), tb_null); - - // the value - object = tb_oc_array_item(object, i); - } - break; - case ']': - default: - p++; - break; - } - - // is macro? done it if be enabled - if ( object - && bmacro - && tb_object_type(object) == TB_OBJECT_TYPE_STRING - && tb_oc_string_size(object) - && tb_oc_string_cstr(object)[0] == '$') - { - // the next path - path = tb_oc_string_cstr(object) + 1; - - // continue to seek it - object = tb_object_seek(root, path, bmacro); - } - } - - // ok? - return object; -} -tb_object_ref_t tb_object_dump(tb_object_ref_t object, tb_size_t format) -{ - // check - tb_assert_and_check_return_val(object, tb_null); - - // data - tb_object_ref_t odata = tb_object_data(object, format); - if (odata) - { - // the data and size - tb_byte_t const* data = (tb_byte_t const*)tb_oc_data_getp(odata); - tb_size_t size = tb_oc_data_size(odata); - if (data && size) - { - // done - tb_char_t const* p = (tb_char_t const*)data; - tb_char_t const* e = (tb_char_t const*)data + size; - tb_char_t b[4096 + 1]; - if (p && p < e) - { - while (p < e && *p && tb_isspace(*p)) p++; - while (p < e && *p) - { - tb_char_t* q = b; - tb_char_t const* d = b + 4096; - for (; p < e && q < d && *p; p++, q++) *q = *p; - *q = '\0'; - tb_printf("%s", b); - } - tb_printf("\n"); - } - } - - // exit data - tb_object_exit(odata); - } - - // the object - return object; -} -tb_size_t tb_object_refn(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object, 0); - - // get it - return object->refn; -} -tb_void_t tb_object_retain(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return(object); - - // readonly? - tb_check_return(!(object->flag & TB_OBJECT_FLAG_READONLY)); - - // refn++ - object->refn++; -} -tb_object_ref_t tb_object_read(tb_stream_ref_t stream) -{ - // check - tb_assert_and_check_return_val(stream, tb_null); - - // done reader - return tb_oc_reader_done(stream); -} -tb_object_ref_t tb_object_read_from_url(tb_char_t const* url) -{ - // check - tb_assert_and_check_return_val(url, tb_null); - - // init - tb_object_ref_t object = tb_null; - - // make stream - tb_stream_ref_t stream = tb_stream_init_from_url(url); - tb_assert_and_check_return_val(stream, tb_null); - - // read object - if (tb_stream_open(stream)) object = tb_object_read(stream); - - // exit stream - tb_stream_exit(stream); - - // ok? - return object; -} -tb_object_ref_t tb_object_read_from_data(tb_byte_t const* data, tb_size_t size) -{ - // check - tb_assert_and_check_return_val(data && size, tb_null); - - // init - tb_object_ref_t object = tb_null; - - // make stream - tb_stream_ref_t stream = tb_stream_init_from_data(data, size); - tb_assert_and_check_return_val(stream, tb_null); - - // read object - if (tb_stream_open(stream)) object = tb_object_read(stream); - - // exit stream - tb_stream_exit(stream); - - // ok? - return object; -} -tb_long_t tb_object_writ(tb_object_ref_t object, tb_stream_ref_t stream, tb_size_t format) -{ - // check - tb_assert_and_check_return_val(object && stream, -1); - - // for xml -#ifndef TB_CONFIG_MODULE_HAVE_XML - tb_assertf(format != TB_OBJECT_FORMAT_XML || format != TB_OBJECT_FORMAT_XPLIST, "please enable xml module first!"); -#endif - - // writ it - return tb_oc_writer_done(object, stream, format); -} -tb_long_t tb_object_writ_to_url(tb_object_ref_t object, tb_char_t const* url, tb_size_t format) -{ - // check - tb_assert_and_check_return_val(object && url, -1); - - // make stream - tb_long_t writ = -1; - tb_stream_ref_t stream = tb_stream_init_from_url(url); - if (stream) - { - // ctrl stream - if (tb_stream_type(stream) == TB_STREAM_TYPE_FILE) - tb_stream_ctrl(stream, TB_STREAM_CTRL_FILE_SET_MODE, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC); - - // open and writ stream - if (tb_stream_open(stream)) writ = tb_object_writ(object, stream, format); - - // exit stream - tb_stream_exit(stream); - } - - // ok? - return writ; -} -tb_long_t tb_object_writ_to_data(tb_object_ref_t object, tb_byte_t* data, tb_size_t size, tb_size_t format) -{ - // check - tb_assert_and_check_return_val(object && data && size, -1); - - // make stream - tb_long_t writ = -1; - tb_stream_ref_t stream = tb_stream_init_from_data(data, size); - if (stream) - { - // open and writ stream - if (tb_stream_open(stream)) writ = tb_object_writ(object, stream, format); - - // exit stream - tb_stream_exit(stream); - } - - // ok? - return writ; -} - diff --git a/core/src/tbox/src/tbox/object/object.h b/core/src/tbox/src/tbox/object/object.h deleted file mode 100644 index 0a3c9108f..000000000 --- a/core/src/tbox/src/tbox/object/object.h +++ /dev/null @@ -1,258 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file object.h - * @defgroup object - * - */ -#ifndef TB_OBJECT_H -#define TB_OBJECT_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "null.h" -#include "data.h" -#include "date.h" -#include "array.h" -#include "string.h" -#include "number.h" -#include "boolean.h" -#include "dictionary.h" -#ifdef TB_CONFIG_API_HAVE_DEPRECATED -# include "deprecated/deprecated.h" -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init object - * - * @param object the object - * @param flag the object flag - * @param type the object type - * - * @return tb_true or tb_false - */ -tb_bool_t tb_object_init(tb_object_ref_t object, tb_size_t flag, tb_size_t type); - -/*! decrease the object reference count, will exit it if --refn == 0 - * - * @param object the object - * - * @note the reference count must be one - */ -tb_void_t tb_object_exit(tb_object_ref_t object); - -/*! clear object - * - * @param object the object - */ -tb_void_t tb_object_clear(tb_object_ref_t object); - -/*! set the object private data - * - * @param object the object - * @param priv the private data - * - */ -tb_void_t tb_object_setp(tb_object_ref_t object, tb_cpointer_t priv); - -/*! get the object private data - * - * @param object the object - * - * @return the private data - */ -tb_cpointer_t tb_object_getp(tb_object_ref_t object); - -/*! read object - * - * @param stream the stream - * - * @return the object - */ -tb_object_ref_t tb_object_read(tb_stream_ref_t stream); - -/*! read object from url - * - * @param url the url - * - * @return the object - */ -tb_object_ref_t tb_object_read_from_url(tb_char_t const* url); - -/*! read object from data - * - * @param data the data - * @param size the size - * - * @return the object - */ -tb_object_ref_t tb_object_read_from_data(tb_byte_t const* data, tb_size_t size); - -/*! writ object - * - * @param object the object - * @param stream the stream - * @param format the object format - * - * @return the writed size, failed: -1 - */ -tb_long_t tb_object_writ(tb_object_ref_t object, tb_stream_ref_t stream, tb_size_t format); - -/*! writ object to url - * - * @param object the object - * @param url the url - * @param format the format - * - * @return the writed size, failed: -1 - */ -tb_long_t tb_object_writ_to_url(tb_object_ref_t object, tb_char_t const* url, tb_size_t format); - -/*! writ object to data - * - * @param object the object - * @param data the data - * @param size the size - * @param format the format - * - * @return the writed size, failed: -1 - */ -tb_long_t tb_object_writ_to_data(tb_object_ref_t object, tb_byte_t* data, tb_size_t size, tb_size_t format); - -/*! copy object - * - * @param object the object - * - * @return the object copy - */ -tb_object_ref_t tb_object_copy(tb_object_ref_t object); - -/*! the object type - * - * @param object the object - * - * @return the object type - */ -tb_size_t tb_object_type(tb_object_ref_t object); - -/*! the object data - * - * @param object the object - * @param format the format - * - * @return the data object - */ -tb_object_ref_t tb_object_data(tb_object_ref_t object, tb_size_t format); - -/*! seek to the object for the gived path - * - * <pre> - * - file: - { - "string": "hello world!" - , "com.xxx.xxx": "hello world" - , "integer": 31415926 - , "array": - [ - "hello world!" - , 31415926 - , 3.1415926 - , false - , true - , { "string": "hello world!" } - ] - , "macro": "$.array[2]" - , "macro2": "$.com\\\\.xxx\\\\.xxx" - , "macro3": "$.macro" - , "macro4": "$.array" - } - - path: - 1. ".string" : hello world! - 2. ".array[1]" : 31415926 - 3. ".array[5].string" : hello world! - 4. ".com\\.xxx\\.xxx" : hello world - 5. ".macro" : 3.1415926 - 6. ".macro2" : hello world - 7. ".macro3" : 3.1415926 - 8. ".macro4[0]" : "hello world!" - - * - * </pre> - * - * @param object the object - * @param path the object path - * @param bmacro enable macro(like "$.path")? - * - * <code> - * tb_object_ref_t object = tb_object_seek(root, ".array[5].string", tb_false); - * if (object) - * { - * tb_trace_d("%s", tb_oc_string_cstr(object)); - * } - * <endcode> - * - * - * @return the object - */ -tb_object_ref_t tb_object_seek(tb_object_ref_t object, tb_char_t const* path, tb_bool_t bmacro); - -/*! dump the object - * - * @param object the object - * @param format the format, support: .xml, .xplist, .json - * - * @return the object - */ -tb_object_ref_t tb_object_dump(tb_object_ref_t object, tb_size_t format); - -/*! the object reference count - * - * @param object the object - * - * @return the object reference count - */ -tb_size_t tb_object_refn(tb_object_ref_t object); - -/*! retain object and increase the object reference count - * - * @param object the object - */ -tb_void_t tb_object_retain(tb_object_ref_t object); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/object/prefix.h b/core/src/tbox/src/tbox/object/prefix.h deleted file mode 100644 index 837adcea6..000000000 --- a/core/src/tbox/src/tbox/object/prefix.h +++ /dev/null @@ -1,104 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_PREFIX_H -#define TB_OBJECT_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../xml/xml.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the object type enum -typedef enum __tb_object_type_e -{ - TB_OBJECT_TYPE_NONE = 0 -, TB_OBJECT_TYPE_DATA = 1 -, TB_OBJECT_TYPE_DATE = 2 -, TB_OBJECT_TYPE_ARRAY = 3 -, TB_OBJECT_TYPE_STRING = 4 -, TB_OBJECT_TYPE_NUMBER = 5 -, TB_OBJECT_TYPE_BOOLEAN = 6 -, TB_OBJECT_TYPE_DICTIONARY = 7 -, TB_OBJECT_TYPE_NULL = 8 -, TB_OBJECT_TYPE_USER = 9 //!< the user defined type, ... - -}tb_object_type_e; - -/// the object flag enum -typedef enum __tb_object_flag_e -{ - TB_OBJECT_FLAG_NONE = 0 -, TB_OBJECT_FLAG_READONLY = 1 -, TB_OBJECT_FLAG_SINGLETON = 2 - -}tb_object_flag_e; - -/// the object format enum -typedef enum __tb_object_format_e -{ - TB_OBJECT_FORMAT_NONE = 0x0000 //!< none -, TB_OBJECT_FORMAT_BIN = 0x0001 //!< the tbox binary format -, TB_OBJECT_FORMAT_BPLIST = 0x0002 //!< the bplist format for apple -, TB_OBJECT_FORMAT_XPLIST = 0x0003 //!< the xplist format for apple -, TB_OBJECT_FORMAT_XML = 0x0004 //!< the xml format -, TB_OBJECT_FORMAT_JSON = 0x0005 //!< the json format -, TB_OBJECT_FORMAT_MAXN = 0x000f //!< the format maxn -, TB_OBJECT_FORMAT_DEFLATE = 0x0100 //!< deflate? - -}tb_object_format_e; - -/// the object type -typedef struct __tb_object_t -{ - /// the object flag - tb_uint8_t flag; - - /// the object type - tb_uint16_t type; - - /// the object reference count - tb_size_t refn; - - /// the object private data - tb_cpointer_t priv; - - /// the copy func - struct __tb_object_t* (*copy)(struct __tb_object_t* object); - - /// the clear func - tb_void_t (*clear)(struct __tb_object_t* object); - - /// the exit func - tb_void_t (*exit)(struct __tb_object_t* object); - -}tb_object_t, *tb_object_ref_t; - -#endif diff --git a/core/src/tbox/src/tbox/object/string.c b/core/src/tbox/src/tbox/object/string.c deleted file mode 100644 index f531bddc4..000000000 --- a/core/src/tbox/src/tbox/object/string.c +++ /dev/null @@ -1,232 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file string.c - * @ingroup object - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "oc_string" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "object.h" -#include "../string/string.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -// the scache string size -#define TB_OBJECT_STRING_CACHE_SIZE (64) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the string type -typedef struct __tb_oc_string_t -{ - // the object base - tb_object_t base; - - // the string - tb_string_t str; - -}tb_oc_string_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -static __tb_inline__ tb_oc_string_t* tb_oc_string_cast(tb_object_ref_t object) -{ - // check - tb_assert_and_check_return_val(object && object->type == TB_OBJECT_TYPE_STRING, tb_null); - - // cast - return (tb_oc_string_t*)object; -} -static tb_object_ref_t tb_oc_string_copy(tb_object_ref_t object) -{ - return tb_oc_string_init_from_cstr(tb_oc_string_cstr(object)); -} -static tb_void_t tb_oc_string_exit(tb_object_ref_t object) -{ - tb_oc_string_t* string = tb_oc_string_cast(object); - if (string) - { - // exit the string - tb_string_exit(&string->str); - - // exit the object - tb_free(object); - } -} -static tb_void_t tb_oc_string_clear(tb_object_ref_t object) -{ - tb_oc_string_t* string = tb_oc_string_cast(object); - if (string) - { - // clear the string - tb_string_clear(&string->str); - } -} -static tb_oc_string_t* tb_oc_string_init_base() -{ - // done - tb_bool_t ok = tb_false; - tb_oc_string_t* string = tb_null; - do - { - // make string - string = tb_malloc0_type(tb_oc_string_t); - tb_assert_and_check_break(string); - - // init string - if (!tb_object_init((tb_object_ref_t)string, TB_OBJECT_FLAG_NONE, TB_OBJECT_TYPE_STRING)) break; - - // init base - string->base.copy = tb_oc_string_copy; - string->base.exit = tb_oc_string_exit; - string->base.clear = tb_oc_string_clear; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (string) tb_object_exit((tb_object_ref_t)string); - string = tb_null; - } - - // ok? - return string; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ -tb_object_ref_t tb_oc_string_init_from_cstr(tb_char_t const* cstr) -{ - // done - tb_bool_t ok = tb_false; - tb_oc_string_t* string = tb_null; - do - { - // make string - string = tb_oc_string_init_base(); - tb_assert_and_check_break(string); - - // init str - if (!tb_string_init(&string->str)) break; - - // copy string - if (cstr) tb_string_cstrcpy(&string->str, cstr); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - tb_oc_string_exit((tb_object_ref_t)string); - string = tb_null; - } - - // ok? - return (tb_object_ref_t)string; -} -tb_object_ref_t tb_oc_string_init_from_str(tb_string_ref_t str) -{ - // done - tb_bool_t ok = tb_false; - tb_oc_string_t* string = tb_null; - do - { - // make string - string = tb_oc_string_init_base(); - tb_assert_and_check_break(string); - - // init str - if (!tb_string_init(&string->str)) break; - - // copy string - if (str) tb_string_strcpy(&string->str, str); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - tb_oc_string_exit((tb_object_ref_t)string); - string = tb_null; - } - - // ok? - return (tb_object_ref_t)string; -} -tb_char_t const* tb_oc_string_cstr(tb_object_ref_t object) -{ - // check - tb_oc_string_t* string = tb_oc_string_cast(object); - tb_assert_and_check_return_val(string, tb_null); - - // cstr - return tb_string_cstr(&string->str); -} -tb_size_t tb_oc_string_cstr_set(tb_object_ref_t object, tb_char_t const* cstr) -{ - // check - tb_oc_string_t* string = tb_oc_string_cast(object); - tb_assert_and_check_return_val(string && cstr, 0); - - // copy string - tb_string_cstrcpy(&string->str, cstr); - - // ok? - return tb_string_size(&string->str); -} -tb_size_t tb_oc_string_size(tb_object_ref_t object) -{ - // check - tb_oc_string_t* string = tb_oc_string_cast(object); - tb_assert_and_check_return_val(string, 0); - - // size - return tb_string_size(&string->str); -} - diff --git a/core/src/tbox/src/tbox/object/string.h b/core/src/tbox/src/tbox/object/string.h deleted file mode 100644 index ce4e6c4eb..000000000 --- a/core/src/tbox/src/tbox/object/string.h +++ /dev/null @@ -1,90 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file string.h - * @ingroup object - * - */ -#ifndef TB_OBJECT_STRING_H -#define TB_OBJECT_STRING_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init string from c-string - * - * @param cstr the c-string - * - * @return the string object - */ -tb_object_ref_t tb_oc_string_init_from_cstr(tb_char_t const* cstr); - -/*! init string from string - * - * @param str the string - * - * @return the string object - */ -tb_object_ref_t tb_oc_string_init_from_str(tb_string_ref_t str); - -/*! the c-string - * - * @param string the string object - * - * @return the c-string - */ -tb_char_t const* tb_oc_string_cstr(tb_object_ref_t string); - -/*! set the c-string - * - * @param string the string object - * @param cstr the c-string - * - * @return the string size - */ -tb_size_t tb_oc_string_cstr_set(tb_object_ref_t string, tb_char_t const* cstr); - -/*! the string size - * - * @param string the string object - * - * @return the string size - */ -tb_size_t tb_oc_string_size(tb_object_ref_t string); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif - diff --git a/core/src/tbox/src/tbox/regex/impl/impl.h b/core/src/tbox/src/tbox/regex/impl/impl.h deleted file mode 100644 index e7d53b619..000000000 --- a/core/src/tbox/src/tbox/regex/impl/impl.h +++ /dev/null @@ -1,48 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_REGEX_IMPL_H -#define TB_REGEX_IMPL_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * private implementation - */ -static tb_void_t tb_regex_match_exit(tb_element_ref_t element, tb_pointer_t buff) -{ - // check - tb_regex_match_ref_t match = (tb_regex_match_ref_t)buff; - tb_assert_and_check_return(match); - - // exit it - if (match->cstr) tb_free(match->cstr); - match->cstr = tb_null; - match->size = 0; -} - -#endif diff --git a/core/src/tbox/src/tbox/regex/impl/pcre.c b/core/src/tbox/src/tbox/regex/impl/pcre.c deleted file mode 100644 index d8165e066..000000000 --- a/core/src/tbox/src/tbox/regex/impl/pcre.c +++ /dev/null @@ -1,357 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file pcre.c - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include <pcre.h> - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the regex type -typedef struct __tb_regex_t -{ - // the code - pcre* code; - - // the results - tb_vector_ref_t results; - - // the mode - tb_size_t mode; - - // the ovector data - tb_int_t* ovector_data; - - // the ovector maxn - tb_size_t ovector_maxn; - - // the buffer data - tb_char_t* buffer_data; - - // the buffer maxn - tb_size_t buffer_maxn; - -}tb_regex_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_regex_ref_t tb_regex_init(tb_char_t const* pattern, tb_size_t mode) -{ - // check - tb_assert_and_check_return_val(pattern, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_regex_t* regex = tb_null; - do - { - // make regex - regex = (tb_regex_t*)tb_malloc0_type(tb_regex_t); - tb_assert_and_check_break(regex); - - // init options - tb_int_t options = 0;//PCRE_UTF8; - if (mode & TB_REGEX_MODE_CASELESS) options |= PCRE_CASELESS; - if (mode & TB_REGEX_MODE_MULTILINE) options |= PCRE_MULTILINE; -#ifndef __tb_debug__ - options |= 0;//PCRE_NO_UTF_CHECK; -#endif - - // init code - tb_char_t const* errorstring = tb_null; - tb_int_t erroroffset = 0; - regex->code = pcre_compile(pattern, options, &errorstring, &erroroffset, tb_null); - if (!regex->code) - { - // trace - tb_trace_d("compile failed at offset %ld: %s\n", (tb_long_t)erroroffset, errorstring); - - // end - break; - } - - // save mode - regex->mode = mode; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (regex) tb_regex_exit((tb_regex_ref_t)regex); - regex = tb_null; - } - - // ok? - return (tb_regex_ref_t)regex; -} -tb_void_t tb_regex_exit(tb_regex_ref_t self) -{ - // check - tb_regex_t* regex = (tb_regex_t*)self; - tb_assert_and_check_return(regex); - - // exit buffer data - if (regex->buffer_data) tb_free(regex->buffer_data); - regex->buffer_data = tb_null; - regex->buffer_maxn = 0; - - // exit ovector - if (regex->ovector_data) tb_free(regex->ovector_data); - regex->ovector_data = tb_null; - regex->ovector_maxn = 0; - - // exit results - if (regex->results) tb_vector_exit(regex->results); - regex->results = tb_null; - - // exit code - if (regex->code) pcre_free(regex->code); - regex->code = tb_null; - - // exit it - tb_free(regex); -} -tb_long_t tb_regex_match(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults) -{ - // check - tb_regex_t* regex = (tb_regex_t*)self; - tb_assert_and_check_return_val(regex && regex->code && cstr, -1); - - // done - tb_long_t ok = -1; - do - { - // clear length first - if (plength) *plength = 0; - - // end? - tb_check_break(start < size); - - // init options -#ifdef __tb_debug__ - tb_uint32_t options = 0; -#else - tb_uint32_t options = 0;//PCRE_NO_UTF_CHECK; -#endif - - // init ovector - if (!regex->ovector_data) - { - regex->ovector_maxn = 3 * 16; - regex->ovector_data = (tb_int_t*)tb_malloc_bytes(sizeof(tb_int_t) * regex->ovector_maxn); - } - tb_assert_and_check_break(regex->ovector_data); - - // match it - tb_long_t count = -1; - while (!(count = pcre_exec(regex->code, tb_null, cstr, size, start, options, regex->ovector_data, regex->ovector_maxn))) - { - // grow ovector - regex->ovector_maxn <<= 1; - regex->ovector_data = (tb_int_t*)tb_ralloc_bytes(regex->ovector_data, sizeof(tb_int_t) * regex->ovector_maxn); - tb_assert_and_check_break(regex->ovector_data); - } - if (count < 0) - { - // no match? - tb_check_break(count != PCRE_ERROR_NOMATCH); - - // trace - tb_trace_d("match failed at offset %lu: error: %ld\n", start, count); - - // end - break; - } - - // check - tb_assertf_and_check_break(count, "ovector has not enough space!"); - - // get the match offset and length - tb_int_t const* ovector = regex->ovector_data; - tb_size_t offset = (tb_size_t)ovector[0]; - tb_size_t length = (tb_size_t)ovector[1] - ovector[0]; - tb_assert_and_check_break(offset + length <= size); - - // trace - tb_trace_d("matched count: %lu, offset: %lu, length: %lu", count, offset, length); - - // save results - if (presults) - { - // init results if not exists - tb_vector_ref_t results = *presults; - if (!results) - { - // init it - if (!regex->results) regex->results = tb_vector_init(16, tb_element_mem(sizeof(tb_regex_match_t), tb_regex_match_exit, tb_null)); - - // save it - *presults = results = regex->results; - } - tb_assert_and_check_break(results); - - // clear it first - tb_vector_clear(results); - - // done - tb_long_t i = 0; - tb_regex_match_t entry; - for (i = 0; i < count; i++) - { - // get substring offset and length - tb_size_t substr_offset = ovector[i << 1]; - tb_size_t substr_length = ovector[(i << 1) + 1] - ovector[i << 1]; - tb_assert_and_check_break(substr_offset + substr_length <= size); - - // make match entry - entry.cstr = tb_strndup(cstr + substr_offset, substr_length); - entry.size = substr_length; - entry.start = substr_offset; - tb_assert_and_check_break(entry.cstr); - - // trace - tb_trace_d(" matched: [%lu, %lu]: %s", entry.start, entry.size, entry.cstr); - - // append it - tb_vector_insert_tail(results, &entry); - } - tb_assert_and_check_break(i == count); - } - - // save length - if (plength) *plength = length; - - // ok - ok = offset; - - } while (0); - - // ok? - return ok; -} -tb_char_t const* tb_regex_replace(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength) -{ - // check - tb_regex_t* regex = (tb_regex_t*)self; - tb_assert_and_check_return_val(regex && cstr && replace_cstr, tb_null); - - // done - tb_char_t const* result = tb_null; - do - { - // clear length first - if (plength) *plength = 0; - - // end? - tb_check_break(start < size); - - // init buffer - if (!regex->buffer_data) - { - regex->buffer_maxn = tb_max(size + replace_size + 64, 256); - regex->buffer_data = tb_malloc_cstr(regex->buffer_maxn); - } - tb_assert_and_check_break(regex->buffer_data); - - // copy cstr - tb_memcpy(regex->buffer_data, cstr, size); - regex->buffer_data[size] = '\0'; - - // done - tb_size_t count = 0; - tb_long_t suboffset = start; - tb_size_t sublength = 0; - tb_size_t length = 0; - tb_vector_ref_t results = tb_null; - while ((suboffset = tb_regex_match(self, regex->buffer_data, size, suboffset + sublength, &sublength, &results)) >= 0 && results) - { - // trace - tb_trace_d("replace: match: [%lu, %lu]", suboffset, sublength); - - // calculate substring end - tb_size_t subend = suboffset + sublength; - tb_assert_and_check_break(subend <= size); - - // update length - length = size - sublength + replace_size; - - // grow buffer - if (regex->buffer_maxn < length) - { - regex->buffer_maxn = tb_max(regex->buffer_maxn << 1, length); - regex->buffer_data = tb_ralloc_cstr(regex->buffer_data, regex->buffer_maxn + 1); - } - tb_assert_and_check_break(regex->buffer_data); - - // replace this match - if (subend < size) tb_memmov(regex->buffer_data + suboffset + replace_size, regex->buffer_data + subend, size - subend); - tb_memcpy(regex->buffer_data + suboffset, replace_cstr, replace_size); - regex->buffer_data[length] = '\0'; - - // trace - tb_trace_d("replace: => %s", regex->buffer_data); - - // update matched count - count++; - - // global replace? - tb_check_break(regex->mode & TB_REGEX_MODE_GLOBAL); - - // update size - size = length; - sublength = replace_size; - } - - // check - tb_check_break(count); - tb_assert_and_check_break(length < regex->buffer_maxn); - - // end - regex->buffer_data[length] = '\0'; - - // trace - tb_trace_d(" replace: [%lu]: %s", length, regex->buffer_data); - - // save length - if (plength) *plength = length; - - // ok - result = (tb_char_t const*)regex->buffer_data; - - } while (0); - - // ok? - return result; -} diff --git a/core/src/tbox/src/tbox/regex/impl/pcre2.c b/core/src/tbox/src/tbox/regex/impl/pcre2.c deleted file mode 100644 index 1ba59698e..000000000 --- a/core/src/tbox/src/tbox/regex/impl/pcre2.c +++ /dev/null @@ -1,351 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file pcre2.c - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include <pcre2.h> - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the regex type -typedef struct __tb_regex_t -{ - // the code - pcre2_code* code; - - // the match data - pcre2_match_data* match_data; - - // the results - tb_vector_ref_t results; - - // the mode - tb_size_t mode; - - // the buffer data - PCRE2_UCHAR* buffer_data; - - // the buffer maxn - tb_size_t buffer_maxn; - -}tb_regex_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_regex_ref_t tb_regex_init(tb_char_t const* pattern, tb_size_t mode) -{ - // check - tb_assert_and_check_return_val(pattern, tb_null); - - // done - tb_bool_t ok = tb_false; - tb_regex_t* regex = tb_null; - do - { - // make regex - regex = (tb_regex_t*)tb_malloc0_type(tb_regex_t); - tb_assert_and_check_break(regex); - - // init options - tb_uint32_t options = PCRE2_UTF; - if (mode & TB_REGEX_MODE_CASELESS) options |= PCRE2_CASELESS; - if (mode & TB_REGEX_MODE_MULTILINE) options |= PCRE2_MULTILINE; -#ifndef __tb_debug__ - options |= PCRE2_NO_UTF_CHECK; -#endif - - // init code - tb_int_t errornumber; - PCRE2_SIZE erroroffset; - regex->code = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, options, &errornumber, &erroroffset, tb_null); - if (!regex->code) - { -#if defined(__tb_debug__) && !defined(TB_CONFIG_OS_WINDOWS) // FIXME: _sprintf undefined link error for vs2015 on windows - // get error info - PCRE2_UCHAR info[256]; - pcre2_get_error_message(errornumber, info, sizeof(info)); - - // trace - tb_trace_d("compile failed at offset %ld: %s\n", (tb_long_t)erroroffset, info); -#endif - - // end - break; - } - - // init match data - regex->match_data = pcre2_match_data_create_from_pattern(regex->code, tb_null); - tb_assert_and_check_break(regex->match_data); - - // save mode - regex->mode = mode; - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (regex) tb_regex_exit((tb_regex_ref_t)regex); - regex = tb_null; - } - - // ok? - return (tb_regex_ref_t)regex; -} -tb_void_t tb_regex_exit(tb_regex_ref_t self) -{ - // check - tb_regex_t* regex = (tb_regex_t*)self; - tb_assert_and_check_return(regex); - - // exit buffer - if (regex->buffer_data) tb_free(regex->buffer_data); - regex->buffer_data = tb_null; - regex->buffer_maxn = 0; - - // exit results - if (regex->results) tb_vector_exit(regex->results); - regex->results = tb_null; - - // exit match data - if (regex->match_data) pcre2_match_data_free(regex->match_data); - regex->match_data = tb_null; - - // exit code - if (regex->code) pcre2_code_free(regex->code); - regex->code = tb_null; - - // exit it - tb_free(regex); -} -tb_long_t tb_regex_match(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults) -{ - // check - tb_regex_t* regex = (tb_regex_t*)self; - tb_assert_and_check_return_val(regex && regex->code && regex->match_data && cstr, -1); - - // done - tb_long_t ok = -1; - do - { - // clear length first - if (plength) *plength = 0; - - // end? - tb_check_break(start < size); - - // init options -#ifdef __tb_debug__ - tb_uint32_t options = 0; -#else - tb_uint32_t options = PCRE2_NO_UTF_CHECK; -#endif - - // match it - tb_long_t count = pcre2_match(regex->code, (PCRE2_SPTR)cstr, (PCRE2_SIZE)size, (PCRE2_SIZE)start, options, regex->match_data, tb_null); - if (count < 0) - { - // no match? - tb_check_break(count != PCRE2_ERROR_NOMATCH); - -#if defined(__tb_debug__) && !defined(TB_CONFIG_OS_WINDOWS) - // get error info - PCRE2_UCHAR info[256]; - pcre2_get_error_message(count, info, sizeof(info)); - - // trace - tb_trace_d("match failed at offset %lu: error: %ld, %s\n", start, count, info); -#endif - - // end - break; - } - - // check - tb_assertf_and_check_break(count, "ovector has not enough space!"); - - // get output vector - PCRE2_SIZE* ovector = pcre2_get_ovector_pointer(regex->match_data); - tb_assert_and_check_break(ovector); - - // get the match offset and length - tb_size_t offset = (tb_size_t)ovector[0]; - tb_size_t length = (tb_size_t)ovector[1] - ovector[0]; - tb_assert_and_check_break(offset + length <= size); - - // trace - tb_trace_d("matched count: %lu, offset: %lu, length: %lu", count, offset, length); - - // save results - if (presults) - { - // init results if not exists - tb_vector_ref_t results = *presults; - if (!results) - { - // init it - if (!regex->results) regex->results = tb_vector_init(16, tb_element_mem(sizeof(tb_regex_match_t), tb_regex_match_exit, tb_null)); - - // save it - *presults = results = regex->results; - } - tb_assert_and_check_break(results); - - // clear it first - tb_vector_clear(results); - - // done - tb_long_t i = 0; - tb_regex_match_t entry; - for (i = 0; i < count; i++) - { - // get substring offset and length - tb_size_t substr_offset = ovector[i << 1]; - tb_size_t substr_length = ovector[(i << 1) + 1] - ovector[i << 1]; - tb_assert_and_check_break(substr_offset + substr_length <= size); - - // make match entry - entry.cstr = tb_strndup(cstr + substr_offset, substr_length); - entry.size = substr_length; - entry.start = substr_offset; - tb_assert_and_check_break(entry.cstr); - - // trace - tb_trace_d(" matched: [%lu, %lu]: %s", entry.start, entry.size, entry.cstr); - - // append it - tb_vector_insert_tail(results, &entry); - } - tb_assert_and_check_break(i == count); - } - - // save length - if (plength) *plength = length; - - // ok - ok = offset; - - } while (0); - - // ok? - return ok; -} -tb_char_t const* tb_regex_replace(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength) -{ - // check - tb_regex_t* regex = (tb_regex_t*)self; - tb_assert_and_check_return_val(regex && regex->code && cstr && replace_cstr, tb_null); - - // done - tb_char_t const* result = tb_null; - do - { - // clear length first - if (plength) *plength = 0; - - // end? - tb_check_break(start < size); - - // init options -#ifdef __tb_debug__ - tb_uint32_t options = 0; -#else - tb_uint32_t options = PCRE2_NO_UTF_CHECK; -#endif - if (regex->mode & TB_REGEX_MODE_GLOBAL) options |= PCRE2_SUBSTITUTE_GLOBAL; - - // init buffer - if (!regex->buffer_data) - { - regex->buffer_maxn = tb_max(size + replace_size + 64, 256); - regex->buffer_data = (PCRE2_UCHAR*)tb_malloc_bytes(regex->buffer_maxn); - } - tb_assert_and_check_break(regex->buffer_data); - - // done - tb_long_t ok = -1; - PCRE2_SIZE length = 0; - while (1) - { - // replace it - length = (PCRE2_SIZE)regex->buffer_maxn; - ok = pcre2_substitute(regex->code, (PCRE2_SPTR)cstr, (PCRE2_SIZE)size, (PCRE2_SIZE)start, options, tb_null, tb_null, (PCRE2_SPTR)replace_cstr, (PCRE2_SIZE)replace_size, regex->buffer_data, &length); - - // no space? - if (ok == PCRE2_ERROR_NOMEMORY) - { - // grow buffer - regex->buffer_maxn <<= 1; - regex->buffer_data = (PCRE2_UCHAR*)tb_ralloc_bytes(regex->buffer_data, regex->buffer_maxn); - tb_assert_and_check_break(regex->buffer_data); - } - // failed - else if (ok < 0) - { -#if defined(__tb_debug__) && !defined(TB_CONFIG_OS_WINDOWS) - // get error info - PCRE2_UCHAR info[256]; - pcre2_get_error_message(ok, info, sizeof(info)); - - // trace - tb_trace_d("replace failed at offset %lu: error: %ld, %s\n", start, ok, info); -#endif - - // end - break; - } - else break; - } - - // check - tb_check_break(ok > 0); - tb_assert_and_check_break(length < regex->buffer_maxn); - - // end - regex->buffer_data[length] = '\0'; - - // trace - tb_trace_d(" replace: [%lu]: %s", length, regex->buffer_data); - - // save length - if (plength) *plength = (tb_size_t)length; - - // ok - result = (tb_char_t const*)regex->buffer_data; - - } while (0); - - // ok? - return result; -} diff --git a/core/src/tbox/src/tbox/regex/impl/prefix.h b/core/src/tbox/src/tbox/regex/impl/prefix.h deleted file mode 100644 index dc39cb8ea..000000000 --- a/core/src/tbox/src/tbox/regex/impl/prefix.h +++ /dev/null @@ -1,38 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_REGEX_IMPL_PREFIX_H -#define TB_REGEX_IMPL_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - - -#endif diff --git a/core/src/tbox/src/tbox/regex/prefix.h b/core/src/tbox/src/tbox/regex/prefix.h deleted file mode 100644 index aa3435a69..000000000 --- a/core/src/tbox/src/tbox/regex/prefix.h +++ /dev/null @@ -1,37 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * @ingroup regex - * - */ -#ifndef TB_REGEX_PREFIX_H -#define TB_REGEX_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../libc/libc.h" -#include "../container/container.h" - - -#endif diff --git a/core/src/tbox/src/tbox/regex/regex.c b/core/src/tbox/src/tbox/regex/regex.c deleted file mode 100644 index 4b516972d..000000000 --- a/core/src/tbox/src/tbox/regex/regex.c +++ /dev/null @@ -1,205 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file regex.c - * @ingroup regex - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "regex" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "regex.h" -#include "impl/impl.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -#if defined(TB_CONFIG_PACKAGE_HAVE_PCRE2) -# include "impl/pcre2.c" -#elif defined(TB_CONFIG_PACKAGE_HAVE_PCRE) -# include "impl/pcre.c" -#elif defined(TB_CONFIG_POSIX_HAVE_REGCOMP) \ - && defined(TB_CONFIG_POSIX_HAVE_REGEXEC) -# include "../platform/posix/regex.c" -#else -tb_regex_ref_t tb_regex_init(tb_char_t const* pattern, tb_size_t mode) -{ - tb_assert_noimpl(); - return tb_null; -} -tb_void_t tb_regex_exit(tb_regex_ref_t regex) -{ - tb_assert_noimpl(); -} -tb_long_t tb_regex_match(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults) -{ - tb_assert_noimpl(); - return -1; -} -tb_char_t const* tb_regex_replace(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength) -{ - tb_assert_noimpl(); - return tb_null; -} -#endif -tb_long_t tb_regex_match_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults) -{ - // check - tb_assert_and_check_return_val(cstr, -1); - - // done - return tb_regex_match(regex, cstr, tb_strlen(cstr), start, plength, presults); -} -tb_vector_ref_t tb_regex_match_simple(tb_regex_ref_t regex, tb_char_t const* cstr) -{ - // check - tb_assert_and_check_return_val(cstr, tb_null); - - // done - tb_vector_ref_t results = tb_null; - return tb_regex_match(regex, cstr, tb_strlen(cstr), 0, tb_null, &results) >= 0? results : tb_null; -} -tb_char_t const* tb_regex_replace_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t* plength) -{ - // check - tb_assert_and_check_return_val(cstr && replace_cstr, tb_null); - - // done - return tb_regex_replace(regex, cstr, tb_strlen(cstr), start, replace_cstr, tb_strlen(replace_cstr), plength); -} -tb_char_t const* tb_regex_replace_simple(tb_regex_ref_t regex, tb_char_t const* cstr, tb_char_t const* replace_cstr) -{ - // check - tb_assert_and_check_return_val(cstr && replace_cstr, tb_null); - - // done - return tb_regex_replace(regex, cstr, tb_strlen(cstr), 0, replace_cstr, tb_strlen(replace_cstr), tb_null); -} -tb_long_t tb_regex_match_done(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults) -{ - // clear results first - if (presults) *presults = tb_null; - - // init regex - tb_long_t ok = -1; - tb_regex_ref_t regex = tb_regex_init(pattern, mode); - if (regex) - { - // init results - tb_vector_ref_t results = tb_vector_init(16, tb_element_mem(sizeof(tb_regex_match_t), tb_regex_match_exit, tb_null)); - if (results) - { - // match regex - ok = tb_regex_match(regex, cstr, size, start, plength, &results); - - // ok? - if (ok >= 0) - { - // save results - if (presults) - { - *presults = results; - results = tb_null; - } - } - - // exit results - if (results) tb_vector_exit(results); - results = tb_null; - } - - // exit regex - tb_regex_exit(regex); - } - - // ok? - return ok; -} -tb_long_t tb_regex_match_done_cstr(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults) -{ - // check - tb_assert_and_check_return_val(cstr, -1); - - // done - return tb_regex_match_done(pattern, mode, cstr, tb_strlen(cstr), start, plength, presults); -} -tb_vector_ref_t tb_regex_match_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr) -{ - // check - tb_assert_and_check_return_val(cstr, tb_null); - - // done - tb_vector_ref_t results = tb_null; - return tb_regex_match_done(pattern, mode, cstr, tb_strlen(cstr), 0, tb_null, &results) >= 0? results : tb_null; -} -tb_char_t const* tb_regex_replace_done(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength) -{ - // clear length first - if (plength) *plength = 0; - - // init regex - tb_char_t* result = tb_null; - tb_regex_ref_t regex = tb_regex_init(pattern, mode); - if (regex) - { - // replace regex - tb_size_t result_size = 0; - tb_char_t const* result_cstr = tb_regex_replace(regex, cstr, size, start, replace_cstr, replace_size, &result_size); - if (result_cstr && result_size) - { - // save result - result = tb_strndup(result_cstr, result_size); - if (result) - { - // save length - if (plength) *plength = result_size; - } - } - - // exit regex - tb_regex_exit(regex); - } - - // ok? - return result; -} -tb_char_t const* tb_regex_replace_done_cstr(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t* plength) -{ - // check - tb_assert_and_check_return_val(cstr && replace_cstr, tb_null); - - // done - return tb_regex_replace_done(pattern, mode, cstr, tb_strlen(cstr), start, replace_cstr, tb_strlen(replace_cstr), tb_null); -} -tb_char_t const* tb_regex_replace_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_char_t const* replace_cstr) -{ - // check - tb_assert_and_check_return_val(cstr && replace_cstr, tb_null); - - // done - return tb_regex_replace_done(pattern, mode, cstr, tb_strlen(cstr), 0, replace_cstr, tb_strlen(replace_cstr), tb_null); -} diff --git a/core/src/tbox/src/tbox/regex/regex.h b/core/src/tbox/src/tbox/regex/regex.h deleted file mode 100644 index 973601c7d..000000000 --- a/core/src/tbox/src/tbox/regex/regex.h +++ /dev/null @@ -1,422 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file regex.h - * @defgroup regex - */ -#ifndef TB_REGEX_H -#define TB_REGEX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the regex ref type -typedef __tb_typeref__(regex); - -/// the regex match type -typedef struct _tb_regex_match_t -{ - /// the c-string data - tb_char_t const* cstr; - - /// the c-string size - tb_size_t size; - - /// the matched start position - tb_size_t start; - -}tb_regex_match_t, *tb_regex_match_ref_t; - -/// the regex mode enum -typedef enum __tb_regex_mode_e -{ - TB_REGEX_MODE_NONE = 0 //!< the default mode -, TB_REGEX_MODE_CASELESS = 1 //!< do caseless matching -, TB_REGEX_MODE_MULTILINE = 2 //!< ^ and $ match newlines within data -, TB_REGEX_MODE_GLOBAL = 4 //!< global replace all - -}tb_regex_mode_e; - - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init regex - * - * @param pattern the regex pattern - * @param mode the regex mode, uses the default mode if be zero - * - * @return the regex - */ -tb_regex_ref_t tb_regex_init(tb_char_t const* pattern, tb_size_t mode); - -/*! exit regex - * - * @param regex the regex - */ -tb_void_t tb_regex_exit(tb_regex_ref_t regex); - -/*! match the given c-string and size by regex - * - * @param regex the regex - * @param cstr the c-string data - * @param size the c-string size - * @param start the start position - * @param plength the matched length pointer, do not get it if be null - * @param presults the results pointer, only match it if be null - * - * @return the matched position, not match: -1 - */ -tb_long_t tb_regex_match(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults); - -/*! match the given c-string by regex - * - * @code - - // init regex - tb_regex_ref_t regex = tb_regex_init("\\w+", 0); - if (regex) - { - // match single - // - // results: "hello" - // - tb_vector_ref_t results = tb_null; - if (tb_regex_match_cstr(regex, "hello world", 0, tb_null, &results) >= 0 && results) - { - // show results - tb_for_all_if (tb_regex_match_ref_t, entry, results, entry) - { - // trace - tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start); - } - } - - // match global - // - // results: "hello" - // results: "world" - // - tb_long_t start = 0; - tb_size_t length = 0; - tb_vector_ref_t results = tb_null; - while ((start = tb_regex_match_cstr(regex, "hello world", start + length, &length, &results)) >= 0 && results) - { - // show results - tb_for_all_if (tb_regex_match_ref_t, entry, results, entry) - { - // trace - tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start); - } - } - - // exit regex - tb_regex_exit(regex); - } - * @endcode - * - * @param regex the regex - * @param cstr the c-string - * @param start the start position - * @param plength the matched length pointer, do not get it if be null - * @param presults the results pointer, only match it if be null - * - * @return the matched position, not match: -1 - */ -tb_long_t tb_regex_match_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults); - -/*! simply match the given c-string by regex - * - * @note only supports single match - * - * @code - - // init regex - tb_regex_ref_t regex = tb_regex_init("\\w+", 0); - if (regex) - { - // match single - // - // results: "hello" - // - tb_vector_ref_t results = tb_regex_match_simple(regex, "hello world"); - if (results) - { - // show results - tb_for_all_if (tb_regex_match_ref_t, entry, results, entry) - { - // trace - tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start); - } - } - - // exit regex - tb_regex_exit(regex); - } - * @endcode - * - * @param regex the regex - * @param cstr the c-string - * - * @return the matched results - */ -tb_vector_ref_t tb_regex_match_simple(tb_regex_ref_t regex, tb_char_t const* cstr); - -/*! replace the given c-string and size by regex - * - * @param regex the regex - * @param cstr the c-string data - * @param size the c-string size - * @param start the start position - * @param replace_cstr the replacement c-string data - * @param replace_size the replacement c-string size - * @param plength the result c-string length pointer, do not get it if be null - * - * @return the result c-string - */ -tb_char_t const* tb_regex_replace(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength); - -/*! replace the given c-string by regex - * - * @param regex the regex - * @param cstr the c-string data - * @param start the start position - * @param replace_cstr the replacement c-string data - * @param plength the result c-string length pointer, do not get it if be null - * - * @return the result c-string - */ -tb_char_t const* tb_regex_replace_cstr(tb_regex_ref_t regex, tb_char_t const* cstr, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t* plength); - -/*! simply replace the given c-string by regex - * - * @code - - // init regex - tb_regex_ref_t regex = tb_regex_init("\\w+", 0); - if (regex) - { - // match single - // - // results: "hi world" - // - tb_char_t const* results = tb_regex_replace_simple(regex, "hello world", "hi"); - if (results) - { - // trace - tb_trace_i("results: %s", results); - } - - // exit regex - tb_regex_exit(regex); - } - * @endcode - * - * @param regex the regex - * @param cstr the c-string data - * @param replace_cstr the replacement c-string data - * - * @return the result c-string - */ -tb_char_t const* tb_regex_replace_simple(tb_regex_ref_t regex, tb_char_t const* cstr, tb_char_t const* replace_cstr); - -/*! match the given c-string and size by the given regex pattern - * - * @param pattern the regex pattern - * @param mode the regex mode, uses the default mode if be zero - * @param cstr the c-string data - * @param size the c-string size - * @param start the start position - * @param plength the matched length pointer, do not get it if be null - * @param presults the results pointer, only match it if be null - * @note we need exit it manually - * - * @return the matched position, not match: -1 - */ -tb_long_t tb_regex_match_done(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults); - -/*! match the given c-string by the given regex pattern - * - * @code - - // match single - // - // results: "hello" - // - tb_vector_ref_t results = tb_null; - if (tb_regex_match_done_cstr("\\w+", 0, "hello world", 0, tb_null, &results) >= 0 && results) - { - // show results - tb_for_all_if (tb_regex_match_ref_t, entry, results, entry) - { - // trace - tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start); - } - - // exit results - tb_vector_exit(results); - } - - // match global - // - // results: "hello" - // results: "world" - // - tb_long_t start = 0; - tb_size_t length = 0; - tb_vector_ref_t results = tb_null; - while ((start = tb_regex_match_done_cstr("\\w+", 0, "hello world", start + length, &length, &results)) >= 0 && results) - { - // show results - tb_for_all_if (tb_regex_match_ref_t, entry, results, entry) - { - // trace - tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start); - } - - // exit results - tb_vector_exit(results); - } - - * @endcode - * - * @param pattern the regex pattern - * @param mode the regex mode, uses the default mode if be zero - * @param cstr the c-string data - * @param start the start position - * @param plength the matched length pointer, do not get it if be null - * @param presults the results pointer, only match it if be null - * @note we need exit it manually - * - * @return the matched position, not match: -1 - */ -tb_long_t tb_regex_match_done_cstr(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults); - -/*! simply match the given c-string by the given regex pattern - * - * @note only supports single match - * - * @code - - // match single - // - // results: "hello" - // - tb_vector_ref_t results = tb_regex_match_done_simple("\\w+", 0, "hello world"); - if (results) - { - // show results - tb_for_all_if (tb_regex_match_ref_t, entry, results, entry) - { - // trace - tb_trace_i("cstr: %s, size: %lu, start: %lu", entry->cstr, entry->size, entry->start); - } - - // exit results - tb_vector_exit(results); - } - - * @endcode - * - * @param pattern the regex pattern - * @param mode the regex mode, uses the default mode if be zero - * @param cstr the c-string data - * - * @return the matched results, we need exit it manually - */ -tb_vector_ref_t tb_regex_match_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr); - -/*! replace the given c-string and size by the given regex pattern - * - * @param pattern the regex pattern - * @param mode the regex mode, uses the default mode if be zero - * @param cstr the c-string data - * @param size the c-string size - * @param start the start position - * @param replace_cstr the replacement c-string data - * @param replace_size the replacement c-string size - * @param plength the result c-string length pointer, do not get it if be null - * - * @return the result c-string - */ -tb_char_t const* tb_regex_replace_done(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t replace_size, tb_size_t* plength); - -/*! replace the given c-string by the given regex pattern - * - * @param pattern the regex pattern - * @param mode the regex mode, uses the default mode if be zero - * @param cstr the c-string data - * @param start the start position - * @param replace_cstr the replacement c-string data - * @param plength the result c-string length pointer, do not get it if be null - * - * @return the result c-string - */ -tb_char_t const* tb_regex_replace_done_cstr(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_size_t start, tb_char_t const* replace_cstr, tb_size_t* plength); - -/*! simply replace the given c-string by the given regex pattern - * - * @code - - // replace single - // - // results: "hi world" - // - tb_char_t const* results = tb_regex_replace_done_simple("\\w+", 0, "hello world", "hi"); - if (results) - { - // trace - tb_trace_i("results: %s", results); - - // exit results - tb_free(results); - } - - * @endcode - * - * @param pattern the regex pattern - * @param mode the regex mode, uses the default mode if be zero - * @param cstr the c-string data - * @param replace_cstr the replacement c-string data - * - * @return the result c-string, @note we need free it manually - */ -tb_char_t const* tb_regex_replace_done_simple(tb_char_t const* pattern, tb_size_t mode, tb_char_t const* cstr, tb_char_t const* replace_cstr); - - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/tbox.c b/core/src/tbox/src/tbox/tbox.c index ad41ee3c0..51a139aac 100644 --- a/core/src/tbox/src/tbox/tbox.c +++ b/core/src/tbox/src/tbox/tbox.c @@ -30,7 +30,6 @@ #include "libc/impl/impl.h" #include "libm/impl/impl.h" #include "math/impl/impl.h" -#include "object/impl/impl.h" #include "memory/impl/impl.h" #include "network/impl/impl.h" #include "platform/impl/impl.h" diff --git a/core/src/tbox/src/tbox/tbox.h b/core/src/tbox/src/tbox/tbox.h index 2c3d85f5e..69c63073a 100644 --- a/core/src/tbox/src/tbox/tbox.h +++ b/core/src/tbox/src/tbox/tbox.h @@ -30,25 +30,19 @@ */ #include "prefix.h" #include "zip/zip.h" -#include "xml/xml.h" -#include "asio/asio.h" #include "libm/libm.h" #include "libc/libc.h" #include "math/math.h" #include "hash/hash.h" #include "utils/utils.h" -#include "regex/regex.h" -#include "object/object.h" #include "memory/memory.h" #include "stream/stream.h" #include "string/string.h" #include "network/network.h" #include "charset/charset.h" #include "platform/platform.h" -#include "database/database.h" #include "algorithm/algorithm.h" #include "container/container.h" -#include "coroutine/coroutine.h" /* ////////////////////////////////////////////////////////////////////////////////////// * extern diff --git a/core/src/tbox/src/tbox/xml/node.c b/core/src/tbox/src/tbox/xml/node.c deleted file mode 100644 index 5d56c1429..000000000 --- a/core/src/tbox/src/tbox/xml/node.c +++ /dev/null @@ -1,466 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file node.c - * @ingroup xml - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "xml" -#define TB_TRACE_MODULE_DEBUG (1) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "node.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_xml_node_ref_t tb_xml_node_init_element(tb_char_t const* name) -{ - // check - tb_assert_and_check_return_val(name, tb_null); - - // make node - tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_element_t); - tb_assert_and_check_return_val(node, tb_null); - - // init - node->type = TB_XML_NODE_TYPE_ELEMENT; - tb_string_init(&node->name); - tb_string_init(&node->data); - tb_string_cstrcpy(&node->name, name); - - // ok - return node; -} -tb_xml_node_ref_t tb_xml_node_init_text(tb_char_t const* data) -{ - // make node - tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_text_t); - tb_assert_and_check_return_val(node, tb_null); - - // init - node->type = TB_XML_NODE_TYPE_TEXT; - tb_string_init(&node->name); - tb_string_init(&node->data); - tb_string_cstrcpy(&node->name, "#text"); - if (data) tb_string_cstrcpy(&node->data, data); - - // ok - return node; -} -tb_xml_node_ref_t tb_xml_node_init_cdata(tb_char_t const* cdata) -{ - // make node - tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_cdata_t); - tb_assert_and_check_return_val(node, tb_null); - - // init - node->type = TB_XML_NODE_TYPE_CDATA; - tb_string_init(&node->name); - tb_string_init(&node->data); - tb_string_cstrcpy(&node->name, "#cdata"); - if (cdata) tb_string_cstrcpy(&node->data, cdata); - - // ok - return node; -} -tb_xml_node_ref_t tb_xml_node_init_comment(tb_char_t const* comment) -{ - // make node - tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_comment_t); - tb_assert_and_check_return_val(node, tb_null); - - // init - node->type = TB_XML_NODE_TYPE_COMMENT; - tb_string_init(&node->name); - tb_string_init(&node->data); - tb_string_cstrcpy(&node->name, "#comment"); - if (comment) tb_string_cstrcpy(&node->data, comment); - - // ok - return node; -} -tb_xml_node_ref_t tb_xml_node_init_attribute(tb_char_t const* name, tb_char_t const* data) -{ - // make node - tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_attribute_t); - tb_assert_and_check_return_val(node, tb_null); - - // init - node->type = TB_XML_NODE_TYPE_ATTRIBUTE; - tb_string_init(&node->name); - tb_string_init(&node->data); - if (name) tb_string_cstrcpy(&node->name, name); - if (data) tb_string_cstrcpy(&node->data, data); - - // ok - return node; -} -tb_xml_node_ref_t tb_xml_node_init_document(tb_char_t const* version, tb_char_t const* charset) -{ - // make node - tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_document_t); - tb_assert_and_check_return_val(node, tb_null); - - // init - node->type = TB_XML_NODE_TYPE_DOCUMENT; - tb_string_init(&node->name); - tb_string_init(&node->data); - tb_string_init(&((tb_xml_document_t*)node)->version); - tb_string_init(&((tb_xml_document_t*)node)->charset); - tb_string_cstrcpy(&node->name, "#document"); - tb_string_cstrcpy(&((tb_xml_document_t*)node)->version, version? version : "2.0"); - tb_string_cstrcpy(&((tb_xml_document_t*)node)->charset, charset? charset : "utf-8"); - - // ok - return node; -} -tb_xml_node_ref_t tb_xml_node_init_document_type(tb_char_t const* type) -{ - // make node - tb_xml_node_ref_t node = (tb_xml_node_ref_t)tb_malloc0_type(tb_xml_document_type_t); - tb_assert_and_check_return_val(node, tb_null); - - // init - node->type = TB_XML_NODE_TYPE_DOCUMENT_TYPE; - tb_string_init(&node->name); - tb_string_init(&node->data); - tb_string_init(&((tb_xml_document_type_t*)node)->type); - tb_string_cstrcpy(&node->name, "#doctype"); - tb_string_cstrcpy(&((tb_xml_document_type_t*)node)->type, type? type : ""); - - // ok - return node; -} -tb_void_t tb_xml_node_exit(tb_xml_node_ref_t node) -{ - if (node) - { - // free name & data - tb_string_exit(&node->name); - tb_string_exit(&node->data); - - // free version & charset for document - if (node->type == TB_XML_NODE_TYPE_DOCUMENT) - { - tb_string_exit(&((tb_xml_document_t*)node)->version); - tb_string_exit(&((tb_xml_document_t*)node)->charset); - } - - // free type - if (node->type == TB_XML_NODE_TYPE_DOCUMENT_TYPE) - tb_string_exit(&((tb_xml_document_type_t*)node)->type); - - // free childs - if (node->chead) - { - tb_xml_node_ref_t save = tb_null; - tb_xml_node_ref_t next = node->chead; - while (next) - { - // save - save = next->next; - - // exit - tb_xml_node_exit(next); - - // next - next = save; - } - } - - // free attributes - if (node->ahead) - { - tb_xml_node_ref_t save = tb_null; - tb_xml_node_ref_t next = node->ahead; - while (next) - { - // save - save = next->next; - - // exit - tb_xml_node_exit(next); - - // next - next = save; - } - } - - // free it - tb_free(node); - } -} -tb_xml_node_ref_t tb_xml_node_chead(tb_xml_node_ref_t node) -{ - // check - tb_assert_and_check_return_val(node, tb_null); - - // get it - return node->chead; -} -tb_size_t tb_xml_node_csize(tb_xml_node_ref_t node) -{ - // check - tb_assert_and_check_return_val(node, 0); - - // get it - return node->csize; -} -tb_xml_node_ref_t tb_xml_node_ahead(tb_xml_node_ref_t node) -{ - // check - tb_assert_and_check_return_val(node, tb_null); - - // get it - return node->ahead; -} -tb_size_t tb_xml_node_asize(tb_xml_node_ref_t node) -{ - // check - tb_assert_and_check_return_val(node, 0); - - // get it - return node->asize; -} -tb_void_t tb_xml_node_insert_next(tb_xml_node_ref_t node, tb_xml_node_ref_t next) -{ - // check - tb_assert_and_check_return(node && next); - - // init - next->parent = node->parent; - next->next = node->next; - - // next - node->next = next; -} -tb_void_t tb_xml_node_remove_next(tb_xml_node_ref_t node) -{ - // check - tb_assert_and_check_return(node); - - // next - tb_xml_node_ref_t next = node->next; - - // save - tb_xml_node_ref_t save = next? next->next : tb_null; - - // exit - if (next) tb_xml_node_exit(next); - - // next - node->next = save; -} -tb_void_t tb_xml_node_append_chead(tb_xml_node_ref_t node, tb_xml_node_ref_t child) -{ - // check - tb_assert_and_check_return(node && child); - - // init - child->parent = node; - - // append - if (node->chead) - { - child->next = node->chead; - node->chead = child; - node->csize++; - } - else - { - tb_assert(!node->ctail); - node->ctail = node->chead = child; - node->csize = 1; - } -} -tb_void_t tb_xml_node_append_ctail(tb_xml_node_ref_t node, tb_xml_node_ref_t child) -{ - // check - tb_assert_and_check_return(node && child); - - // init - child->parent = node; - child->next = tb_null; - - // append - if (node->ctail) - { - node->ctail->next = child; - node->ctail = child; - node->csize++; - } - else - { - tb_assert(!node->chead); - node->ctail = node->chead = child; - node->csize = 1; - } -} -tb_void_t tb_xml_node_remove_chead(tb_xml_node_ref_t node) -{ - // check - tb_assert_and_check_return(node); - - // null? - tb_check_return(node->chead); - - // remove - if (node->chead != node->ctail) - { - // save - tb_xml_node_ref_t save = node->chead; - - // remove - node->chead = save->next; - - // exit - tb_xml_node_exit(save); - - // size-- - node->csize--; - } - else - { - // save - tb_xml_node_ref_t save = node->chead; - - // remove - node->chead = tb_null; - node->ctail = tb_null; - - // exit - tb_xml_node_exit(save); - - // size-- - node->csize--; - } -} -tb_void_t tb_xml_node_remove_ctail(tb_xml_node_ref_t node) -{ - tb_trace_noimpl(); -} -tb_void_t tb_xml_node_append_ahead(tb_xml_node_ref_t node, tb_xml_node_ref_t attribute) -{ - // check - tb_assert_and_check_return(node && attribute); - - // init - attribute->parent = node; - - // append - if (node->ahead) - { - attribute->next = node->ahead; - node->ahead = attribute; - node->asize++; - } - else - { - tb_assert(!node->atail); - node->atail = node->ahead = attribute; - node->asize = 1; - } -} -tb_void_t tb_xml_node_append_atail(tb_xml_node_ref_t node, tb_xml_node_ref_t attribute) -{ - // check - tb_assert_and_check_return(node && attribute); - - // init - attribute->parent = node; - attribute->next = tb_null; - - // append - if (node->atail) - { - node->atail->next = attribute; - node->atail = attribute; - node->asize++; - } - else - { - tb_assert(!node->ahead); - node->atail = node->ahead = attribute; - node->asize = 1; - } -} -tb_xml_node_ref_t tb_xml_node_goto(tb_xml_node_ref_t node, tb_char_t const* path) -{ - // check - tb_assert_and_check_return_val(node && path, tb_null); - - // trace - tb_trace_d("root: %s goto: %s", tb_string_cstr(&node->name), path); - - // skip '/' - tb_char_t const* p = path; while (*p && *p == '/') p++; - - // is self? - if (!*p) return node; - - // size - tb_size_t n = tb_strlen(p); - - // walk the child nodes - tb_xml_node_ref_t head = node->chead; - for (node = head; node; node = node->next) - { - if (node->type == TB_XML_NODE_TYPE_ELEMENT) - { - // size - tb_size_t m = tb_string_size(&node->name); - - // trace - tb_trace_d("%s", tb_string_cstr(&node->name)); - - // has it? - if (!tb_string_cstrncmp(&node->name, p, m)) - { - // is it? - if (m == n) return node; - else if (m < n) - { - // skip this node - tb_char_t const* q = p + m; - - // is root? - if (*q == '/') - { - // goto the child node - tb_xml_node_ref_t c = tb_xml_node_goto(node, q); - if (c) return c; - } - } - } - } - } - - // no - return tb_null; -} - diff --git a/core/src/tbox/src/tbox/xml/node.h b/core/src/tbox/src/tbox/xml/node.h deleted file mode 100644 index 26c5aeedf..000000000 --- a/core/src/tbox/src/tbox/xml/node.h +++ /dev/null @@ -1,333 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file node.h - * @ingroup xml - * - */ -#ifndef TB_XML_NODE_H -#define TB_XML_NODE_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/*! the xml node type - * - * @note see http://www.w3.org/TR/REC-DOM-Level-1/ - * - */ -typedef enum __tb_xml_node_type_t -{ - TB_XML_NODE_TYPE_NONE = 0 -, TB_XML_NODE_TYPE_ELEMENT = 1 -, TB_XML_NODE_TYPE_ATTRIBUTE = 2 -, TB_XML_NODE_TYPE_TEXT = 3 -, TB_XML_NODE_TYPE_CDATA = 4 -, TB_XML_NODE_TYPE_ENTITY_REFERENCE = 5 -, TB_XML_NODE_TYPE_ENTITY = 6 -, TB_XML_NODE_TYPE_PROCESSING_INSTRUCTION = 7 -, TB_XML_NODE_TYPE_COMMENT = 8 -, TB_XML_NODE_TYPE_DOCUMENT = 9 -, TB_XML_NODE_TYPE_DOCUMENT_TYPE = 10 -, TB_XML_NODE_TYPE_DOCUMENT_FRAGMENT = 11 -, TB_XML_NODE_TYPE_NOTATION = 12 - -}tb_xml_node_type_t; - -/// the xml node -typedef struct __tb_xml_node_t -{ - /// the node type - tb_size_t type; - - /// the node name - tb_string_t name; - - /// the node data - tb_string_t data; - - /// the next - struct __tb_xml_node_t* next; - - /// the childs head - struct __tb_xml_node_t* chead; - - /// the childs tail - struct __tb_xml_node_t* ctail; - - /// the childs size - tb_size_t csize; - - /// the attributes head - struct __tb_xml_node_t* ahead; - - /// the attributes tail - struct __tb_xml_node_t* atail; - - /// the attributes size - tb_size_t asize; - - /// the parent - struct __tb_xml_node_t* parent; - -}tb_xml_node_t; - -/// the xml element type -typedef struct __tb_xml_element_t -{ - /// the node base - tb_xml_node_t base; - -}tb_xml_element_t; - -/// the xml text type -typedef struct __tb_xml_text_t -{ - /// the node base - tb_xml_node_t base; - -}tb_xml_text_t; - -/// the xml cdata type -typedef struct __tb_xml_cdata_t -{ - /// the node base - tb_xml_node_t base; - -}tb_xml_cdata_t; - -/// the xml comment type -typedef struct __tb_xml_comment_t -{ - /// the node base - tb_xml_node_t base; - -}tb_xml_comment_t; - -/*! the xml attribute type - * - * <pre> - * inherit node, - * but since they are not actually child nodes of the element they describe, - * the DOM does not consider them part of the document tree. - * </pre> - */ -typedef struct __tb_xml_attribute_t -{ - /// the node base - tb_xml_node_t base; - -}tb_xml_attribute_t; - -/// the xml document type -typedef struct __tb_xml_document_t -{ - /// the node base - tb_xml_node_t base; - - /// the version - tb_string_t version; - - /// the charset - tb_string_t charset; - -}tb_xml_document_t; - -/// the xml document type type -typedef struct __tb_xml_document_type_t -{ - /// the node base - tb_xml_node_t base; - - /// the type - tb_string_t type; - -}tb_xml_document_type_t; - -/// the xml node ref type -typedef tb_xml_node_t* tb_xml_node_ref_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init element node - * - * @param name the element name - * @return the element node - */ -tb_xml_node_ref_t tb_xml_node_init_element(tb_char_t const* name); - -/*! init text node - * - * @param data the element text - * @return the element node - */ -tb_xml_node_ref_t tb_xml_node_init_text(tb_char_t const* data); - -/*! init cdata node - * - * @param cdata the element cdata - * @return the element node - */ -tb_xml_node_ref_t tb_xml_node_init_cdata(tb_char_t const* cdata); - -/*! init comment node - * - * @param comment the element comment - * @return the element node - */ -tb_xml_node_ref_t tb_xml_node_init_comment(tb_char_t const* comment); - -/*! init attribute node - * - * @param name the attribute name - * @param data the attribute data - * @return the element node - */ -tb_xml_node_ref_t tb_xml_node_init_attribute(tb_char_t const* name, tb_char_t const* data); - -/*! init document node - * - * @param version the xml version - * @param encoding the xml encoding - * @return the element node - */ -tb_xml_node_ref_t tb_xml_node_init_document(tb_char_t const* version, tb_char_t const* encoding); - -/*! init document type node - * - * @param type the document type - * @return the element node - */ -tb_xml_node_ref_t tb_xml_node_init_document_type(tb_char_t const* type); - -/*! exit the xml node - * - * @param node the element node - */ -tb_void_t tb_xml_node_exit(tb_xml_node_ref_t node); - -/*! goto node by the gived path - * - * @param node the root node - * @return the goto node - */ -tb_xml_node_ref_t tb_xml_node_goto(tb_xml_node_ref_t node, tb_char_t const* path); - -/*! the xml childs head node - * - * @param node the xml node - * @return the xml childs head node - */ -tb_xml_node_ref_t tb_xml_node_chead(tb_xml_node_ref_t node); - -/*! the xml childs count - * - * @param node the xml node - * @return the xml childs count - */ -tb_size_t tb_xml_node_csize(tb_xml_node_ref_t node); - -/*! the xml attributes head node - * - * @param node the xml node - * @return the xml attributes head node - */ -tb_xml_node_ref_t tb_xml_node_ahead(tb_xml_node_ref_t node); - -/*! the xml attributes count - * - * @param node the xml node - * @return the xml attributes count - */ -tb_size_t tb_xml_node_asize(tb_xml_node_ref_t node); - -/*! insert to the next node - * - * @param node the xml node - * @param next the xml next node - */ -tb_void_t tb_xml_node_insert_next(tb_xml_node_ref_t node, tb_xml_node_ref_t next); - -/*! remove the next node - * - * @param node the xml node - */ -tb_void_t tb_xml_node_remove_next(tb_xml_node_ref_t node); - -/*! append the node to the childs head - * - * @param node the xml node - * @param child the xml child node - */ -tb_void_t tb_xml_node_append_chead(tb_xml_node_ref_t node, tb_xml_node_ref_t child); - -/*! append the node to the childs tail - * - * @param node the xml node - * @param child the xml child node - */ -tb_void_t tb_xml_node_append_ctail(tb_xml_node_ref_t node, tb_xml_node_ref_t child); - -/*! remove the node from the childs head - * - * @param node the xml node - */ -tb_void_t tb_xml_node_remove_chead(tb_xml_node_ref_t node); - -/*! remove the node from the childs tail - * - * @param node the xml node - */ -tb_void_t tb_xml_node_remove_ctail(tb_xml_node_ref_t node); - -/*! append the node to the attributes head - * - * @param node the xml node - * @param attribute the xml attribute node - */ -tb_void_t tb_xml_node_append_ahead(tb_xml_node_ref_t node, tb_xml_node_ref_t attribute); - -/*! append the node to the attributes tail - * - * @param node the xml node - * @param attribute the xml attribute node - */ -tb_void_t tb_xml_node_append_atail(tb_xml_node_ref_t node, tb_xml_node_ref_t attribute); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/xml/prefix.h b/core/src/tbox/src/tbox/xml/prefix.h deleted file mode 100644 index 471c79aaf..000000000 --- a/core/src/tbox/src/tbox/xml/prefix.h +++ /dev/null @@ -1,41 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file prefix.h - * - */ -#ifndef TB_XML_PREFIX_H -#define TB_XML_PREFIX_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "../prefix.h" -#include "../libc/libc.h" -#include "../utils/utils.h" -#include "../stream/stream.h" -#include "../string/string.h" -#include "../memory/memory.h" -#include "../platform/platform.h" -#include "../container/container.h" - - -#endif diff --git a/core/src/tbox/src/tbox/xml/reader.c b/core/src/tbox/src/tbox/xml/reader.c deleted file mode 100644 index 370e52fc5..000000000 --- a/core/src/tbox/src/tbox/xml/reader.c +++ /dev/null @@ -1,928 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file reader.c - * @ingroup xml - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "xml" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "reader.h" -#include "../charset/charset.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ - -#ifdef __tb_small__ -# define TB_XML_READER_ATTRIBUTES_MAXN (64) -#else -# define TB_XML_READER_ATTRIBUTES_MAXN (128) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the xml reader impl type -typedef struct __tb_xml_reader_impl_t -{ - // the event - tb_size_t event; - - // the level - tb_size_t level; - - // is bowner of the input stream? - tb_bool_t bowner; - - // the input stream - tb_stream_ref_t istream; - - // the filter stream - tb_stream_ref_t fstream; - - // the reader stream - tb_stream_ref_t rstream; - - // the version - tb_string_t version; - - // the charset - tb_string_t charset; - - // the element - tb_string_t element; - - // the element name - tb_string_t element_name; - - // the text - tb_string_t text; - - // the attribute name - tb_string_t attribute_name; - - // the attribute data - tb_string_t attribute_data; - - // the attributes - tb_xml_attribute_t attributes[TB_XML_READER_ATTRIBUTES_MAXN]; - -}tb_xml_reader_impl_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * parser implementation - */ -static tb_char_t const* tb_xml_reader_element_parse(tb_xml_reader_impl_t* reader) -{ - // clear element - tb_string_clear(&reader->element); - - // parse element - tb_char_t ch = '\0'; - tb_size_t in = 0; - while (tb_stream_bread_s8(reader->rstream, (tb_sint8_t*)&ch)) - { - // append element - if (!in && ch == '<') in = 1; - else if (in) - { - if (ch != '>') tb_string_chrcat(&reader->element, ch); - else return tb_string_cstr(&reader->element); - } - } - - // failed - tb_assertf(0, "invalid element: %s from %s", tb_string_cstr(&reader->element), tb_url_cstr(tb_stream_url(reader->istream))); - return tb_null; -} -static tb_char_t const* tb_xml_reader_text_parse(tb_xml_reader_impl_t* reader) -{ - // clear text - tb_string_clear(&reader->text); - - // parse text - tb_char_t* pc = tb_null; - while (tb_stream_need(reader->rstream, (tb_byte_t**)&pc, 1) && pc) - { - // is end? </ ..> - if (pc[0] == '<') return tb_string_cstr(&reader->text); - else - { - tb_string_chrcat(&reader->text, *pc); - if (!tb_stream_skip(reader->rstream, 1)) return tb_null; - } - } - return tb_null; -} - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_xml_reader_ref_t tb_xml_reader_init() -{ - // init reader - tb_xml_reader_impl_t* reader = tb_malloc0_type(tb_xml_reader_impl_t); - tb_assert_and_check_return_val(reader, tb_null); - - // init string - tb_string_init(&reader->text); - tb_string_init(&reader->version); - tb_string_init(&reader->charset); - tb_string_init(&reader->element); - tb_string_init(&reader->element_name); - tb_string_init(&reader->attribute_name); - tb_string_init(&reader->attribute_data); - tb_string_cstrcpy(&reader->version, "2.0"); - tb_string_cstrcpy(&reader->charset, "utf-8"); - - // init attributes - tb_size_t i = 0; - for (i = 0; i < TB_XML_READER_ATTRIBUTES_MAXN; i++) - { - tb_xml_node_ref_t node = (tb_xml_node_ref_t)(reader->attributes + i); - tb_string_init(&node->name); - tb_string_init(&node->data); - } - - // ok - return (tb_xml_reader_ref_t)reader; -} -tb_void_t tb_xml_reader_exit(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return(impl); - - // clos it first - tb_xml_reader_clos(reader); - - // exit the filter stream - if (impl->fstream) tb_stream_exit(impl->fstream); - - // exit text - tb_string_exit(&impl->text); - - // exit version - tb_string_exit(&impl->version); - - // exit charset - tb_string_exit(&impl->charset); - - // exit element - tb_string_exit(&impl->element); - - // exit element name - tb_string_exit(&impl->element_name); - - // exit attribute name - tb_string_exit(&impl->attribute_name); - - // exit attribute data - tb_string_exit(&impl->attribute_data); - - // exit attributes - tb_long_t i = 0; - for (i = 0; i < TB_XML_READER_ATTRIBUTES_MAXN; i++) - { - tb_xml_node_ref_t node = (tb_xml_node_ref_t)(impl->attributes + i); - tb_string_exit(&node->name); - tb_string_exit(&node->data); - } - - // free it - tb_free(impl); -} -tb_bool_t tb_xml_reader_open(tb_xml_reader_ref_t reader, tb_stream_ref_t stream, tb_bool_t bowner) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl && stream, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // check - tb_assert_and_check_break(!impl->rstream && !impl->istream); - - // init level - impl->level = 0; - - // init owner - impl->bowner = bowner; - - // init the input stream - impl->istream = stream; - - // init the reader stream - impl->rstream = stream; - - // open the reader stream if be not opened - if (!tb_stream_is_opened(impl->rstream) && !tb_stream_open(impl->rstream)) break; - - // clear text - tb_string_clear(&impl->text); - - // clear element - tb_string_clear(&impl->element); - - // clear name - tb_string_clear(&impl->element_name); - - // clear attribute name - tb_string_clear(&impl->attribute_name); - - // clear attribute data - tb_string_clear(&impl->attribute_data); - - // clear attributes - tb_long_t i = 0; - for (i = 0; i < TB_XML_READER_ATTRIBUTES_MAXN; i++) - { - tb_xml_node_ref_t node = (tb_xml_node_ref_t)(impl->attributes + i); - tb_string_clear(&node->name); - tb_string_clear(&node->data); - } - - // ok - ok = tb_true; - - } while (0); - - // failed? close it - if (!ok) tb_xml_reader_clos(reader); - - // ok? - return ok; -} -tb_void_t tb_xml_reader_clos(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return(impl); - - // clos the reader stream - if (impl->rstream) tb_stream_clos(impl->rstream); - impl->rstream = tb_null; - - // exit the input stream - if (impl->istream && impl->bowner) tb_stream_exit(impl->istream); - impl->istream = tb_null; - - // clear level - impl->level = 0; - - // clear owner - impl->bowner = tb_false; - - // clear text - tb_string_clear(&impl->text); - - // clear element - tb_string_clear(&impl->element); - - // clear name - tb_string_clear(&impl->element_name); - - // clear attribute name - tb_string_clear(&impl->attribute_name); - - // clear attribute data - tb_string_clear(&impl->attribute_data); - - // clear attributes - tb_long_t i = 0; - for (i = 0; i < TB_XML_READER_ATTRIBUTES_MAXN; i++) - { - tb_xml_node_ref_t node = (tb_xml_node_ref_t)(impl->attributes + i); - tb_string_clear(&node->name); - tb_string_clear(&node->data); - } -} -tb_stream_ref_t tb_xml_reader_stream(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl, tb_null); - - return impl->rstream; -} -tb_size_t tb_xml_reader_level(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl, 0); - - return impl->level; -} -tb_size_t tb_xml_reader_next(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl && impl->rstream, TB_XML_READER_EVENT_NONE); - - // reset event - impl->event = TB_XML_READER_EVENT_NONE; - - // next - while (!impl->event) - { - // peek character - tb_char_t* pc = tb_null; - if (!tb_stream_need(impl->rstream, (tb_byte_t**)&pc, 1) || !pc) break; - - // is element? - if (*pc == '<') - { - // parse element: <...> - tb_char_t const* element = tb_xml_reader_element_parse(impl); - tb_assert_and_check_break(element); - - // is document begin: <?xml version="..." charset=".." ?> - tb_size_t size = tb_string_size(&impl->element); - if (size > 4 && !tb_strnicmp(element, "?xml", 4)) - { - // update event - impl->event = TB_XML_READER_EVENT_DOCUMENT; - - // update version & charset - tb_xml_node_ref_t attr = (tb_xml_node_ref_t)tb_xml_reader_attributes(reader); - for (; attr; attr = attr->next) - { - if (!tb_string_cstricmp(&attr->name, "version")) tb_string_strcpy(&impl->version, &attr->data); - if (!tb_string_cstricmp(&attr->name, "encoding")) tb_string_strcpy(&impl->charset, &attr->data); - } - - // transform stream => utf-8 - if (tb_string_cstricmp(&impl->charset, "utf-8") && tb_string_cstricmp(&impl->charset, "utf8")) - { - // charset - tb_size_t charset = TB_CHARSET_TYPE_UTF8; - if (!tb_string_cstricmp(&impl->charset, "gb2312") || !tb_string_cstricmp(&impl->charset, "gbk")) - charset = TB_CHARSET_TYPE_GB2312; - else tb_trace_e("the charset: %s is not supported", tb_string_cstr(&impl->charset)); - - // init transform stream - if (charset != TB_CHARSET_TYPE_UTF8) - { -#ifdef TB_CONFIG_MODULE_HAVE_CHARSET - // init the filter stream - if (!impl->fstream) impl->fstream = tb_stream_init_filter_from_charset(impl->istream, charset, TB_CHARSET_TYPE_UTF8); - else - { - // ctrl stream - if (!tb_stream_ctrl(impl->fstream, TB_STREAM_CTRL_FLTR_SET_STREAM, impl->istream)) break; - - // the filter - tb_filter_ref_t filter = tb_null; - if (!tb_stream_ctrl(impl->fstream, TB_STREAM_CTRL_FLTR_GET_FILTER, &filter)) break; - tb_assert_and_check_break(filter); - - // ctrl filter - if (!tb_filter_ctrl(filter, TB_FILTER_CTRL_CHARSET_SET_FTYPE, charset)) break; - } - - // open the filter stream - if (impl->fstream && tb_stream_open(impl->fstream)) - impl->rstream = impl->fstream; - tb_string_cstrcpy(&impl->charset, "utf-8"); -#else - // trace - tb_trace_e("unicode type is not supported, please enable charset module config if you want to use it!"); -#endif - } - } - } - // is document type: <!DOCTYPE ... > - else if (size > 8 && !tb_strnicmp(element, "!DOCTYPE", 8)) - { - // update event - impl->event = TB_XML_READER_EVENT_DOCUMENT_TYPE; - } - // is element end: </name> - else if (size > 1 && element[0] == '/') - { - // check - tb_check_break(impl->level); - - // update event - impl->event = TB_XML_READER_EVENT_ELEMENT_END; - - // leave - impl->level--; - } - // is comment: <!-- text --> - else if (size >= 3 && !tb_strncmp(element, "!--", 3)) - { - // no comment end? - if (element[size - 2] != '-' || element[size - 1] != '-') - { - // patch '>' - tb_string_chrcat(&impl->element, '>'); - - // seek to comment end - tb_char_t ch = '\0'; - tb_int_t n = 0; - while (tb_stream_bread_s8(impl->rstream, (tb_sint8_t*)&ch)) - { - // --> - if (n == 2 && ch == '>') break; - else - { - // append it - tb_string_chrcat(&impl->element, ch); - - if (ch == '-') n++; - else n = 0; - } - } - - // update event - if (ch != '\0') impl->event = TB_XML_READER_EVENT_COMMENT; - } - else impl->event = TB_XML_READER_EVENT_COMMENT; - } - // is cdata: <![CDATA[ text ]]> - else if (size >= 8 && !tb_strnicmp(element, "![CDATA[", 8)) - { - if (element[size - 2] != ']' || element[size - 1] != ']') - { - // patch '>' - tb_string_chrcat(&impl->element, '>'); - - // seek to cdata end - tb_char_t ch = '\0'; - tb_int_t n = 0; - while (tb_stream_bread_s8(impl->rstream, (tb_sint8_t*)&ch)) - { - // ]]> - if (n == 2 && ch == '>') break; - else - { - // append it - tb_string_chrcat(&impl->element, ch); - - if (ch == ']') n++; - else n = 0; - } - } - - // update event - if (ch != '\0') impl->event = TB_XML_READER_EVENT_CDATA; - } - else impl->event = TB_XML_READER_EVENT_CDATA; - } - // is empty element: <name/> - else if (size > 1 && element[size - 1] == '/') - { - // update event - impl->event = TB_XML_READER_EVENT_ELEMENT_EMPTY; - } - // is element begin: <name> - else - { - // update event - impl->event = TB_XML_READER_EVENT_ELEMENT_BEG; - - // enter - impl->level++; - } - - // trace -// tb_trace_d("<%s>", element); - } - // is text: <> text </> - else if (*pc) - { - // parse text: <> ... <> - tb_char_t const* text = tb_xml_reader_text_parse(impl); - if (text && tb_string_cstrcmp(&impl->text, "\r\n") && tb_string_cstrcmp(&impl->text, "\n")) - impl->event = TB_XML_READER_EVENT_TEXT; - - // trace -// tb_trace_d("%s", text); - } - else - { - // skip the invalid character - if (!tb_stream_skip(impl->rstream, 1)) break; - } - } - - // ok? - return impl->event; -} -tb_bool_t tb_xml_reader_goto(tb_xml_reader_ref_t reader, tb_char_t const* path) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl && impl->rstream && path, tb_false); - - // trace - tb_trace_d("goto: %s", path); - - // init level - impl->level = 0; - - // seek to the stream head - if (!tb_stream_seek(impl->rstream, 0)) return tb_false; - - // init - tb_static_string_t s; - tb_char_t data[8192]; - if (!tb_static_string_init(&s, data, 8192)) return tb_false; - - // save the current offset - tb_hize_t save = tb_stream_offset(impl->rstream); - - // done - tb_bool_t ok = tb_false; - tb_bool_t leave = tb_false; - tb_size_t event = TB_XML_READER_EVENT_NONE; - while (!leave && !ok && (event = tb_xml_reader_next(reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_ELEMENT_EMPTY: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // append - tb_size_t n = tb_static_string_size(&s); - tb_static_string_chrcat(&s, '/'); - tb_static_string_cstrcat(&s, name); - - // ok? - if (!tb_static_string_cstricmp(&s, path)) ok = tb_true; - - // trace - tb_trace_d("path: %s", tb_static_string_cstr(&s)); - - // remove - tb_static_string_strip(&s, n); - - // restore - if (ok) if (!(ok = tb_stream_seek(impl->rstream, save))) leave = tb_true; - } - break; - case TB_XML_READER_EVENT_ELEMENT_BEG: - { - // name - tb_char_t const* name = tb_xml_reader_element(reader); - tb_assert_and_check_break_state(name, leave, tb_true); - - // append - tb_static_string_chrcat(&s, '/'); - tb_static_string_cstrcat(&s, name); - - // ok? - if (!tb_static_string_cstricmp(&s, path)) ok = tb_true; - - // trace - tb_trace_d("path: %s", tb_static_string_cstr(&s)); - - // restore - if (ok) if (!(ok = tb_stream_seek(impl->rstream, save))) leave = tb_true; - } - break; - case TB_XML_READER_EVENT_ELEMENT_END: - { - // remove - tb_long_t p = tb_static_string_strrchr(&s, 0, '/'); - if (p >= 0) tb_static_string_strip(&s, p); - - // ok? - if (!tb_static_string_cstricmp(&s, path)) ok = tb_true; - - // trace - tb_trace_d("path: %s", tb_static_string_cstr(&s)); - - // restore - if (ok) if (!(ok = tb_stream_seek(impl->rstream, save))) leave = tb_true; - } - break; - default: - break; - } - - // save - save = tb_stream_offset(impl->rstream); - } - - // exit string - tb_static_string_exit(&s); - - // clear level - impl->level = 0; - - // failed? restore to the stream head - if (!ok) tb_stream_seek(impl->rstream, 0); - - // ok? - return ok; -} -tb_xml_node_ref_t tb_xml_reader_load(tb_xml_reader_ref_t reader) -{ - // check - tb_assert_and_check_return_val(reader, tb_null); - - // done - tb_bool_t ok = tb_true; - tb_xml_node_ref_t node = tb_null; - tb_size_t event = TB_XML_READER_EVENT_NONE; - while (ok && (event = tb_xml_reader_next(reader))) - { - // init document node - if (!node) - { - node = tb_xml_node_init_document(tb_xml_reader_version(reader), tb_xml_reader_charset(reader)); - tb_assert_and_check_break_state(node && !node->parent, ok, tb_false); - } - - switch (event) - { - case TB_XML_READER_EVENT_DOCUMENT: - break; - case TB_XML_READER_EVENT_DOCUMENT_TYPE: - { - // init - tb_xml_node_ref_t doctype = tb_xml_node_init_document_type(tb_xml_reader_doctype(reader)); - tb_assert_and_check_break_state(doctype, ok, tb_false); - - // append - tb_xml_node_append_ctail(node, doctype); - tb_assert_and_check_break_state(doctype->parent, ok, tb_false); - } - break; - case TB_XML_READER_EVENT_ELEMENT_EMPTY: - { - // init - tb_xml_node_ref_t element = tb_xml_node_init_element(tb_xml_reader_element(reader)); - tb_assert_and_check_break_state(element, ok, tb_false); - - // attributes - tb_xml_node_ref_t attr = tb_xml_reader_attributes(reader); - for (; attr; attr = attr->next) - tb_xml_node_append_atail(element, tb_xml_node_init_attribute(tb_string_cstr(&attr->name), tb_string_cstr(&attr->data))); - - // append - tb_xml_node_append_ctail(node, element); - tb_assert_and_check_break_state(element->parent, ok, tb_false); - } - break; - case TB_XML_READER_EVENT_ELEMENT_BEG: - { - // init - tb_xml_node_ref_t element = tb_xml_node_init_element(tb_xml_reader_element(reader)); - tb_assert_and_check_break_state(element, ok, tb_false); - - // attributes - tb_xml_node_ref_t attr = tb_xml_reader_attributes(reader); - for (; attr; attr = attr->next) - tb_xml_node_append_atail(element, tb_xml_node_init_attribute(tb_string_cstr(&attr->name), tb_string_cstr(&attr->data))); - - // append - tb_xml_node_append_ctail(node, element); - tb_assert_and_check_break_state(element->parent, ok, tb_false); - - // enter - node = element; - } - break; - case TB_XML_READER_EVENT_ELEMENT_END: - { - // check - tb_assert_and_check_break_state(node, ok, tb_false); - - // the parent node - node = node->parent; - } - break; - case TB_XML_READER_EVENT_TEXT: - { - // init - tb_xml_node_ref_t text = tb_xml_node_init_text(tb_xml_reader_text(reader)); - tb_assert_and_check_break_state(text, ok, tb_false); - - // append - tb_xml_node_append_ctail(node, text); - tb_assert_and_check_break_state(text->parent, ok, tb_false); - } - break; - case TB_XML_READER_EVENT_CDATA: - { - // init - tb_xml_node_ref_t cdata = tb_xml_node_init_cdata(tb_xml_reader_cdata(reader)); - tb_assert_and_check_break_state(cdata, ok, tb_false); - - // append - tb_xml_node_append_ctail(node, cdata); - tb_assert_and_check_break_state(cdata->parent, ok, tb_false); - - } - break; - case TB_XML_READER_EVENT_COMMENT: - { - // init - tb_xml_node_ref_t comment = tb_xml_node_init_comment(tb_xml_reader_comment(reader)); - tb_assert_and_check_break_state(comment, ok, tb_false); - - // append - tb_xml_node_append_ctail(node, comment); - tb_assert_and_check_break_state(comment->parent, ok, tb_false); - } - break; - default: - break; - } - } - - // failed? - if (!ok) - { - // exit it - if (node) tb_xml_node_exit(node); - node = tb_null; - } - - // ok - return node; -} -tb_char_t const* tb_xml_reader_version(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl, tb_null); - - // text - return tb_string_cstr(&impl->version); -} -tb_char_t const* tb_xml_reader_charset(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl, tb_null); - - // text - return tb_string_cstr(&impl->charset); -} -tb_char_t const* tb_xml_reader_comment(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl && impl->event == TB_XML_READER_EVENT_COMMENT, tb_null); - - // init - tb_char_t const* p = tb_string_cstr(&impl->element); - tb_size_t n = tb_string_size(&impl->element); - tb_assert_and_check_return_val(p && n >= 6, tb_null); - - // comment - tb_string_cstrncpy(&impl->text, p + 3, n - 5); - return tb_string_cstr(&impl->text); -} -tb_char_t const* tb_xml_reader_cdata(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl && impl->event == TB_XML_READER_EVENT_CDATA, tb_null); - - // init - tb_char_t const* p = tb_string_cstr(&impl->element); - tb_size_t n = tb_string_size(&impl->element); - tb_assert_and_check_return_val(p && n >= 11, tb_null); - - // comment - tb_string_cstrncpy(&impl->text, p + 8, n - 10); - return tb_string_cstr(&impl->text); -} -tb_char_t const* tb_xml_reader_text(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl && impl->event == TB_XML_READER_EVENT_TEXT, tb_null); - - // text - return tb_string_cstr(&impl->text); -} -tb_char_t const* tb_xml_reader_element(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl && ( impl->event == TB_XML_READER_EVENT_ELEMENT_BEG - || impl->event == TB_XML_READER_EVENT_ELEMENT_END - || impl->event == TB_XML_READER_EVENT_ELEMENT_EMPTY), tb_null); - - // init - tb_char_t const* p = tb_null; - tb_char_t const* b = tb_string_cstr(&impl->element); - tb_char_t const* e = b + tb_string_size(&impl->element); - tb_assert_and_check_return_val(b, tb_null); - - // </name> or <name ... /> - if (b < e && *b == '/') b++; - for (p = b; p < e && *p && !tb_isspace(*p) && *p != '/'; p++) ; - - // ok? - return p > b? tb_string_cstrncpy(&impl->element_name, b, p - b) : tb_null; -} -tb_char_t const* tb_xml_reader_doctype(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl && impl->event == TB_XML_READER_EVENT_DOCUMENT_TYPE, tb_null); - - // doctype - tb_char_t const* p = tb_string_cstr(&impl->element); - tb_assert_and_check_return_val(p, tb_null); - - // skip !DOCTYPE - return (p + 9); -} -tb_xml_node_ref_t tb_xml_reader_attributes(tb_xml_reader_ref_t reader) -{ - // check - tb_xml_reader_impl_t* impl = (tb_xml_reader_impl_t*)reader; - tb_assert_and_check_return_val(impl && ( impl->event == TB_XML_READER_EVENT_DOCUMENT - || impl->event == TB_XML_READER_EVENT_ELEMENT_BEG - || impl->event == TB_XML_READER_EVENT_ELEMENT_END - || impl->event == TB_XML_READER_EVENT_ELEMENT_EMPTY), tb_null); - - // init - tb_char_t const* p = tb_string_cstr(&impl->element); - tb_char_t const* e = p + tb_string_size(&impl->element); - - // skip name - while (p < e && *p && !tb_isspace(*p)) p++; - while (p < e && *p && tb_isspace(*p)) p++; - - // parse attributes - tb_size_t n = 0; - while (p < e) - { - // parse name - tb_string_clear(&impl->attribute_name); - for (; p < e && *p != '='; p++) if (!tb_isspace(*p)) tb_string_chrcat(&impl->attribute_name, *p); - if (*p != '=') break; - - // parse data - tb_string_clear(&impl->attribute_data); - for (p++; p < e && (*p != '\'' && *p != '\"'); p++) ; - if (*p != '\'' && *p != '\"') break; - for (p++; p < e && (*p != '\'' && *p != '\"'); p++) tb_string_chrcat(&impl->attribute_data, *p); - if (*p != '\'' && *p != '\"') break; - p++; - - // append node - if (tb_string_cstr(&impl->attribute_name) && tb_string_cstr(&impl->attribute_data)) - { - // node - tb_xml_node_ref_t prev = n > 0? (tb_xml_node_ref_t)&impl->attributes[n - 1] : tb_null; - tb_xml_node_ref_t node = (tb_xml_node_ref_t)&impl->attributes[n]; - - // init node - tb_string_strcpy(&node->name, &impl->attribute_name); - tb_string_strcpy(&node->data, &impl->attribute_data); - - // append node - if (prev) prev->next = node; - node->next = tb_null; - - // next - n++; - } - } - - // ok? - return n? (tb_xml_node_ref_t)&impl->attributes[0] : tb_null; -} diff --git a/core/src/tbox/src/tbox/xml/reader.h b/core/src/tbox/src/tbox/xml/reader.h deleted file mode 100644 index 29a2a7068..000000000 --- a/core/src/tbox/src/tbox/xml/reader.h +++ /dev/null @@ -1,298 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file reader.h - * @ingroup xml - * - */ -#ifndef TB_XML_READER_H -#define TB_XML_READER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "node.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the xml reader event type for iterator -typedef enum __tb_xml_reader_event_t -{ - TB_XML_READER_EVENT_NONE = 0 -, TB_XML_READER_EVENT_DOCUMENT_TYPE = 1 -, TB_XML_READER_EVENT_DOCUMENT = 2 -, TB_XML_READER_EVENT_ELEMENT_BEG = 3 -, TB_XML_READER_EVENT_ELEMENT_END = 4 -, TB_XML_READER_EVENT_ELEMENT_EMPTY = 5 -, TB_XML_READER_EVENT_COMMENT = 6 -, TB_XML_READER_EVENT_TEXT = 7 -, TB_XML_READER_EVENT_CDATA = 8 - -}tb_xml_reader_event_t; - -/// the xml reader ref type -typedef __tb_typeref__(xml_reader); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init the xml reader - * - * @return the reader - */ -tb_xml_reader_ref_t tb_xml_reader_init(tb_noarg_t); - -/*! exit the xml reader - * - * @param reader the xml reader - */ -tb_void_t tb_xml_reader_exit(tb_xml_reader_ref_t reader); - -/*! open the xml reader - * - * @param reader the xml reader - * @param stream the stream, will open it if be not opened - * @param bowner the xml reader is owner of the stream? - * - * @return tb_true or tb_false - */ -tb_bool_t tb_xml_reader_open(tb_xml_reader_ref_t reader, tb_stream_ref_t stream, tb_bool_t bowner); - -/*! clos the xml reader - * - * @param reader the xml reader - */ -tb_void_t tb_xml_reader_clos(tb_xml_reader_ref_t reader); - -/*! the next iterator for the xml reader - * - * @param reader the xml reader - * @return the iterator event - * - * @code - * - // init reader - tb_xml_reader_ref_t reader = tb_xml_reader_init(); - if (reader) - { - // open reader - if (tb_xml_reader_open(reader, tb_stream_init_from_url(argv[1]), tb_true)) - { - // goto - tb_bool_t ok = tb_true; - if (argv[2]) ok = tb_xml_reader_goto(reader, argv[2]); - - // walk - tb_size_t event = TB_XML_READER_EVENT_NONE; - while (ok && (event = tb_xml_reader_next(reader))) - { - switch (event) - { - case TB_XML_READER_EVENT_DOCUMENT: - { - tb_printf("<?xml version = \"%s\" encoding = \"%s\" ?>\n" - , tb_xml_reader_version(reader), tb_xml_reader_charset(reader)); - } - break; - case TB_XML_READER_EVENT_DOCUMENT_TYPE: - { - tb_printf("<!DOCTYPE>\n"); - } - break; - case TB_XML_READER_EVENT_ELEMENT_EMPTY: - { - tb_char_t const* name = tb_xml_reader_element(reader); - tb_xml_node_ref_t attr = tb_xml_reader_attributes(reader); - tb_size_t t = tb_xml_reader_level(reader); - while (t--) tb_printf("\t"); - if (!attr) tb_printf("<%s/>\n", name); - else - { - tb_printf("<%s", name); - for (; attr; attr = attr->next) - tb_printf(" %s = \"%s\"", tb_string_cstr(&attr->name), tb_string_cstr(&attr->data)); - tb_printf("/>\n"); - } - } - break; - case TB_XML_READER_EVENT_ELEMENT_BEG: - { - tb_char_t const* name = tb_xml_reader_element(reader); - tb_xml_node_ref_t attr = tb_xml_reader_attributes(reader); - tb_size_t t = tb_xml_reader_level(reader) - 1; - while (t--) tb_printf("\t"); - if (!attr) tb_printf("<%s>\n", name); - else - { - tb_printf("<%s", name); - for (; attr; attr = attr->next) - tb_printf(" %s = \"%s\"", tb_string_cstr(&attr->name), tb_string_cstr(&attr->data)); - tb_printf(">\n"); - } - } - break; - case TB_XML_READER_EVENT_ELEMENT_END: - { - tb_size_t t = tb_xml_reader_level(reader); - while (t--) tb_printf("\t"); - tb_printf("</%s>\n", tb_xml_reader_element(reader)); - } - break; - case TB_XML_READER_EVENT_TEXT: - { - tb_size_t t = tb_xml_reader_level(reader); - while (t--) tb_printf("\t"); - tb_printf("%s", tb_xml_reader_text(reader)); - tb_printf("\n"); - } - break; - case TB_XML_READER_EVENT_CDATA: - { - tb_size_t t = tb_xml_reader_level(reader); - while (t--) tb_printf("\t"); - tb_printf("<![CDATA[%s]]>", tb_xml_reader_cdata(reader)); - tb_printf("\n"); - } - break; - case TB_XML_READER_EVENT_COMMENT: - { - tb_size_t t = tb_xml_reader_level(reader); - while (t--) tb_printf("\t"); - tb_printf("<!--%s-->", tb_xml_reader_comment(reader)); - tb_printf("\n"); - } - break; - default: - break; - } - } - } - - // exit reader - tb_xml_reader_exit(reader); - } - - * @endcode - */ -tb_size_t tb_xml_reader_next(tb_xml_reader_ref_t reader); - -/*! the xml stream - * - * @param reader the xml reader - * @return the xml stream - */ -tb_stream_ref_t tb_xml_reader_stream(tb_xml_reader_ref_t reader); - -/*! the xml level - * - * @param reader the xml reader - * @return the xml level for tab spaces - */ -tb_size_t tb_xml_reader_level(tb_xml_reader_ref_t reader); - -/*! seek to the given node for xml, .e.g /root/node/item - * - * @param reader the reader handle - * @param path the xml path - * @return tb_true or tb_false - * - * @note the stream will be reseted - */ -tb_bool_t tb_xml_reader_goto(tb_xml_reader_ref_t reader, tb_char_t const* path); - -/*! load the xml - * - * @param reader the xml reader - * @return the xml root node - */ -tb_xml_node_ref_t tb_xml_reader_load(tb_xml_reader_ref_t reader); - -/*! the xml version - * - * @param reader the xml reader - * @return the xml version - */ -tb_char_t const* tb_xml_reader_version(tb_xml_reader_ref_t reader); - -/*! the xml charset - * - * @param reader the xml reader - * @return the xml charset - */ -tb_char_t const* tb_xml_reader_charset(tb_xml_reader_ref_t reader); - -/*! the current xml element name - * - * @param reader the xml reader - * @return the current xml element name - */ -tb_char_t const* tb_xml_reader_element(tb_xml_reader_ref_t reader); - -/*! the current xml node text - * - * @param reader the xml reader - * @return the current xml node text - */ -tb_char_t const* tb_xml_reader_text(tb_xml_reader_ref_t reader); - -/*! the current xml node cdata - * - * @param reader the xml reader - * @return the current xml node cdata - */ -tb_char_t const* tb_xml_reader_cdata(tb_xml_reader_ref_t reader); - -/*! the current xml node comment - * - * @param reader the xml reader - * @return the current xml node comment - */ -tb_char_t const* tb_xml_reader_comment(tb_xml_reader_ref_t reader); - -/*! the xml document type - * - * @param reader the xml reader - * @return the xml document type - */ -tb_char_t const* tb_xml_reader_doctype(tb_xml_reader_ref_t reader); - -/*! the current xml node attributes - * - * @param reader the xml reader - * @return the current xml node attributes - */ -tb_xml_node_ref_t tb_xml_reader_attributes(tb_xml_reader_ref_t reader); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/xml/writer.c b/core/src/tbox/src/tbox/xml/writer.c deleted file mode 100644 index 63b1342b2..000000000 --- a/core/src/tbox/src/tbox/xml/writer.c +++ /dev/null @@ -1,497 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file writer.c - * @ingroup xml - * - */ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * trace - */ -#define TB_TRACE_MODULE_NAME "xml" -#define TB_TRACE_MODULE_DEBUG (0) - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "writer.h" -#include "../charset/charset.h" -#include "../algorithm/algorithm.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * macros - */ -#ifdef __tb_small__ -# define TB_XML_WRITER_ELEMENTS_GROW (32) -#else -# define TB_XML_WRITER_ELEMENTS_GROW (64) -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -// the xml writer impl type -typedef struct __tb_xml_writer_impl_t -{ - // stream - tb_stream_ref_t stream; - - // is format? - tb_bool_t bformat; - - // is owner of the stream? - tb_bool_t bowner; - - // the elements stack - tb_stack_ref_t elements; - - // the attributes hash - tb_hash_map_ref_t attributes; - -}tb_xml_writer_impl_t; - -/* ////////////////////////////////////////////////////////////////////////////////////// - * implementation - */ -tb_xml_writer_ref_t tb_xml_writer_init() -{ - // done - tb_bool_t ok = tb_false; - tb_xml_writer_impl_t* writer = tb_null; - do - { - // make writer - writer = tb_malloc0_type(tb_xml_writer_impl_t); - tb_assert_and_check_break(writer); - - // init elements - writer->elements = tb_stack_init(TB_XML_WRITER_ELEMENTS_GROW, tb_element_str(tb_false)); - tb_assert_and_check_break(writer->elements); - - // init attributes - writer->attributes = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_str(tb_false), tb_element_str(tb_false)); - tb_assert_and_check_break(writer->attributes); - - // ok - ok = tb_true; - - } while (0); - - // failed? - if (!ok) - { - // exit it - if (writer) tb_xml_writer_exit((tb_xml_writer_ref_t)writer); - writer = tb_null; - } - - // ok? - return (tb_xml_writer_ref_t)writer; -} -tb_void_t tb_xml_writer_exit(tb_xml_writer_ref_t writer) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl); - - // clos it first - tb_xml_writer_clos(writer); - - // exit attributes - if (impl->attributes) tb_hash_map_exit(impl->attributes); - impl->attributes = tb_null; - - // exit elements - if (impl->elements) tb_stack_exit(impl->elements); - impl->elements = tb_null; - - // free it - tb_free(impl); -} -tb_bool_t tb_xml_writer_open(tb_xml_writer_ref_t writer, tb_bool_t bformat, tb_stream_ref_t stream, tb_bool_t bowner) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return_val(impl && stream, tb_false); - - // done - tb_bool_t ok = tb_false; - do - { - // check - tb_assert_and_check_break(!impl->stream); - - // init format - impl->bformat = bformat; - - // init owner - impl->bowner = bowner; - - // init stream - impl->stream = stream; - - // ctrl stream - if (tb_stream_type(stream) == TB_STREAM_TYPE_FILE) - { - // ctrl mode - if (!tb_stream_ctrl(stream, TB_STREAM_CTRL_FILE_SET_MODE, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC)) break; - } - - // open the reader stream if be not opened - if (!tb_stream_is_opened(impl->stream) && !tb_stream_open(impl->stream)) break; - - // ok - ok = tb_true; - - } while (0); - - // failed? close it - if (!ok) tb_xml_writer_clos(writer); - - // ok? - return ok; -} -tb_void_t tb_xml_writer_clos(tb_xml_writer_ref_t writer) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl); - - // clos stream - if (impl->stream) tb_stream_clos(impl->stream); - - // exit stream - if (impl->stream && impl->bowner) tb_stream_exit(impl->stream); - impl->stream = tb_null; - - // clear owner - impl->bowner = tb_false; - - // clear format - impl->bformat = tb_false; - - // clear attributes - if (impl->attributes) tb_hash_map_clear(impl->attributes); - - // clear elements - if (impl->elements) tb_stack_clear(impl->elements); -} -tb_void_t tb_xml_writer_save(tb_xml_writer_ref_t writer, tb_xml_node_ref_t node) -{ - // check - tb_assert_and_check_return(writer && node); - - // done - switch (node->type) - { - case TB_XML_NODE_TYPE_DOCUMENT: - { - // document - tb_xml_document_t* document = (tb_xml_document_t*)node; - tb_xml_writer_document(writer, tb_string_cstr(&document->version), tb_string_cstr(&document->charset)); - - // childs - tb_xml_node_ref_t next = node->chead; - while (next) - { - // save - tb_xml_writer_save(writer, next); - - // next - next = next->next; - } - } - break; - case TB_XML_NODE_TYPE_DOCUMENT_TYPE: - { - // document type - tb_xml_document_type_t* doctype = (tb_xml_document_type_t*)node; - tb_xml_writer_document_type(writer, tb_string_cstr(&doctype->type)); - } - break; - case TB_XML_NODE_TYPE_ELEMENT: - { - // attributes - tb_xml_node_ref_t attr = node->ahead; - while (attr) - { - // save - tb_xml_writer_attributes_cstr(writer, tb_string_cstr(&attr->name), tb_string_cstr(&attr->data)); - - // next - attr = attr->next; - } - - // childs - tb_xml_node_ref_t next = node->chead; - if (next) - { - // enter - tb_xml_writer_element_enter(writer, tb_string_cstr(&node->name)); - - // init - while (next) - { - // save - tb_xml_writer_save(writer, next); - - // next - next = next->next; - } - - // leave - tb_xml_writer_element_leave(writer); - } - else tb_xml_writer_element_empty(writer, tb_string_cstr(&node->name)); - } - break; - case TB_XML_NODE_TYPE_COMMENT: - tb_xml_writer_comment(writer, tb_string_cstr(&node->data)); - break; - case TB_XML_NODE_TYPE_CDATA: - tb_xml_writer_cdata(writer, tb_string_cstr(&node->data)); - break; - case TB_XML_NODE_TYPE_TEXT: - tb_xml_writer_text(writer, tb_string_cstr(&node->data)); - break; - default: - break; - } -} -tb_void_t tb_xml_writer_document(tb_xml_writer_ref_t writer, tb_char_t const* version, tb_char_t const* charset) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->stream); - - tb_stream_printf(impl->stream, "<?xml version=\"%s\" encoding=\"%s\"?>", version? version : "2.0", charset? charset : "utf-8"); - if (impl->bformat) tb_stream_printf(impl->stream, "\n"); -} -tb_void_t tb_xml_writer_document_type(tb_xml_writer_ref_t writer, tb_char_t const* type) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->stream); - - tb_stream_printf(impl->stream, "<!DOCTYPE %s>", type? type : ""); - if (impl->bformat) tb_stream_printf(impl->stream, "\n"); -} -tb_void_t tb_xml_writer_cdata(tb_xml_writer_ref_t writer, tb_char_t const* data) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->stream && data); - - // writ tabs - if (impl->bformat) - { - tb_size_t t = tb_stack_size(impl->elements); - while (t--) tb_stream_printf(impl->stream, "\t"); - } - - tb_stream_printf(impl->stream, "<![CDATA[%s]]>", data); - if (impl->bformat) tb_stream_printf(impl->stream, "\n"); -} -tb_void_t tb_xml_writer_text(tb_xml_writer_ref_t writer, tb_char_t const* text) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->stream && text); - - // writ tabs - if (impl->bformat) - { - tb_size_t t = tb_stack_size(impl->elements); - while (t--) tb_stream_printf(impl->stream, "\t"); - } - - tb_stream_printf(impl->stream, "%s", text); - if (impl->bformat) tb_stream_printf(impl->stream, "\n"); -} -tb_void_t tb_xml_writer_comment(tb_xml_writer_ref_t writer, tb_char_t const* comment) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->stream && comment); - - // writ tabs - if (impl->bformat) - { - tb_size_t t = tb_stack_size(impl->elements); - while (t--) tb_stream_printf(impl->stream, "\t"); - } - - tb_stream_printf(impl->stream, "<!--%s-->", comment); - if (impl->bformat) tb_stream_printf(impl->stream, "\n"); -} -tb_void_t tb_xml_writer_element_empty(tb_xml_writer_ref_t writer, tb_char_t const* name) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->stream && impl->attributes && name); - - // writ tabs - if (impl->bformat) - { - tb_size_t t = tb_stack_size(impl->elements); - while (t--) tb_stream_printf(impl->stream, "\t"); - } - - // writ name - tb_stream_printf(impl->stream, "<%s", name); - - // writ attributes - if (tb_hash_map_size(impl->attributes)) - { - tb_for_all (tb_hash_map_item_ref_t, item, impl->attributes) - { - if (item && item->name && item->data) - tb_stream_printf(impl->stream, " %s=\"%s\"", item->name, item->data); - } - tb_hash_map_clear(impl->attributes); - } - - // writ end - tb_stream_printf(impl->stream, "/>"); - if (impl->bformat) tb_stream_printf(impl->stream, "\n"); -} -tb_void_t tb_xml_writer_element_enter(tb_xml_writer_ref_t writer, tb_char_t const* name) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->stream && impl->elements && impl->attributes && name); - - // writ tabs - if (impl->bformat) - { - tb_size_t t = tb_stack_size(impl->elements); - while (t--) tb_stream_printf(impl->stream, "\t"); - } - - // writ name - tb_stream_printf(impl->stream, "<%s", name); - - // writ attributes - if (tb_hash_map_size(impl->attributes)) - { - tb_for_all (tb_hash_map_item_ref_t, item, impl->attributes) - { - if (item && item->name && item->data) - tb_stream_printf(impl->stream, " %s=\"%s\"", item->name, item->data); - } - tb_hash_map_clear(impl->attributes); - } - - // writ end - tb_stream_printf(impl->stream, ">"); - if (impl->bformat) tb_stream_printf(impl->stream, "\n"); - - // put name - tb_stack_put(impl->elements, name); -} -tb_void_t tb_xml_writer_element_leave(tb_xml_writer_ref_t writer) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->stream && impl->elements && impl->attributes); - - // writ tabs - if (impl->bformat) - { - tb_size_t t = tb_stack_size(impl->elements); - if (t) t--; - while (t--) tb_stream_printf(impl->stream, "\t"); - } - - // writ name - tb_char_t const* name = (tb_char_t const*)tb_stack_top(impl->elements); - tb_assert_and_check_return(name); - - tb_stream_printf(impl->stream, "</%s>", name); - if (impl->bformat) tb_stream_printf(impl->stream, "\n"); - - // pop name - tb_stack_pop(impl->elements); -} -tb_void_t tb_xml_writer_attributes_long(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_long_t value) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->attributes && name); - - tb_char_t data[64] = {0}; - tb_snprintf(data, 64, "%ld", value); - tb_hash_map_insert(impl->attributes, name, data); -} -tb_void_t tb_xml_writer_attributes_bool(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_bool_t value) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->attributes && name); - - tb_char_t data[64] = {0}; - tb_snprintf(data, 64, "%s", value? "true" : "false"); - tb_hash_map_insert(impl->attributes, name, data); -} -tb_void_t tb_xml_writer_attributes_cstr(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_char_t const* value) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->attributes && name && value); - - tb_hash_map_insert(impl->attributes, name, value); -} -tb_void_t tb_xml_writer_attributes_format(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_char_t const* format, ...) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->attributes && name && format); - - tb_size_t size = 0; - tb_char_t data[8192] = {0}; - tb_vsnprintf_format(data, 8192, format, &size); - tb_hash_map_insert(impl->attributes, name, data); -} -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -tb_void_t tb_xml_writer_attributes_float(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_float_t value) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->attributes && name); - - tb_char_t data[64] = {0}; - tb_snprintf(data, 64, "%f", value); - tb_hash_map_insert(impl->attributes, name, data); -} -tb_void_t tb_xml_writer_attributes_double(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_double_t value) -{ - // check - tb_xml_writer_impl_t* impl = (tb_xml_writer_impl_t*)writer; - tb_assert_and_check_return(impl && impl->attributes && name); - - tb_char_t data[64] = {0}; - tb_snprintf(data, 64, "%lf", value); - tb_hash_map_insert(impl->attributes, name, data); -} -#endif - diff --git a/core/src/tbox/src/tbox/xml/writer.h b/core/src/tbox/src/tbox/xml/writer.h deleted file mode 100644 index 6a763db6b..000000000 --- a/core/src/tbox/src/tbox/xml/writer.h +++ /dev/null @@ -1,198 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file writer.h - * @ingroup xml - * - */ -#ifndef TB_XML_WRITER_H -#define TB_XML_WRITER_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "node.h" - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_enter__ - -/* ////////////////////////////////////////////////////////////////////////////////////// - * types - */ - -/// the xml writer ref type -typedef __tb_typeref__(xml_writer); - -/* ////////////////////////////////////////////////////////////////////////////////////// - * interfaces - */ - -/*! init the xml writer - * - * @return the writer - */ -tb_xml_writer_ref_t tb_xml_writer_init(tb_noarg_t); - -/*! exit the xml writer - * - * @param writer the xml writer - */ -tb_void_t tb_xml_writer_exit(tb_xml_writer_ref_t writer); - -/*! open the xml writer - * - * @param writer the xml writer - * @param bformat is format xml? - * @param stream the stream, will open it if be not opened - * @param bowner the xml writer is owner of the stream? - * - * @return tb_true or tb_false - */ -tb_bool_t tb_xml_writer_open(tb_xml_writer_ref_t writer, tb_bool_t bformat, tb_stream_ref_t stream, tb_bool_t bowner); - -/*! clos the xml writer - * - * @param writer the xml writer - */ -tb_void_t tb_xml_writer_clos(tb_xml_writer_ref_t writer); - -/*! save the xml document or node - * - * @param writer the xml writer - * @param node the xml node - */ -tb_void_t tb_xml_writer_save(tb_xml_writer_ref_t writer, tb_xml_node_ref_t node); - -/*! writ the xml document node: <?xml version = \"...\" encoding = \"...\" ?> - * - * @param writer the xml writer - * @param version the xml version - * @param encoding the xml encoding - */ -tb_void_t tb_xml_writer_document(tb_xml_writer_ref_t writer, tb_char_t const* version, tb_char_t const* encoding); - -/*! writ the xml document type: <!DOCTYPE type> - * - * @param writer the xml writer - * @param type the xml document type - */ -tb_void_t tb_xml_writer_document_type(tb_xml_writer_ref_t writer, tb_char_t const* type); - -/*! writ the xml cdata: <![CDATA[...]]> - * - * @param writer the xml writer - * @param data the xml cdata - */ -tb_void_t tb_xml_writer_cdata(tb_xml_writer_ref_t writer, tb_char_t const* data); - -/*! writ the xml text - * - * @param writer the xml writer - * @param text the xml text - */ -tb_void_t tb_xml_writer_text(tb_xml_writer_ref_t writer, tb_char_t const* text); - -/*! writ the xml comment: <!-- ... --> - * - * @param writer the xml writer - * @param comment the xml comment - */ -tb_void_t tb_xml_writer_comment(tb_xml_writer_ref_t writer, tb_char_t const* comment); - -/*! writ the empty xml element: <name/> - * - * @param writer the xml writer - * @param name the xml element name - */ -tb_void_t tb_xml_writer_element_empty(tb_xml_writer_ref_t writer, tb_char_t const* name); - -/*! writ the xml element head: <name> ... - * - * @param writer the xml writer - * @param name the xml element name - */ -tb_void_t tb_xml_writer_element_enter(tb_xml_writer_ref_t writer, tb_char_t const* name); - -/*! writ the xml element tail: ... </name> - * - * @param writer the xml writer - */ -tb_void_t tb_xml_writer_element_leave(tb_xml_writer_ref_t writer); - -/*! writ the xml attribute for long value - * - * @param writer the xml writer - * @param name the xml attribute name - * @param value the xml attribute value - */ -tb_void_t tb_xml_writer_attributes_long(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_long_t value); - -/*! writ the xml attribute for boolean value - * - * @param writer the xml writer - * @param name the xml attribute name - * @param value the xml attribute value - */ -tb_void_t tb_xml_writer_attributes_bool(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_bool_t value); - -/*! writ the xml attribute for cstr value - * - * @param writer the xml writer - * @param name the xml attribute name - * @param value the xml attribute value - */ -tb_void_t tb_xml_writer_attributes_cstr(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_char_t const* value); - -/*! writ the xml attribute for format value - * - * @param writer the xml writer - * @param name the xml attribute name - * @param format the xml attribute format - */ -tb_void_t tb_xml_writer_attributes_format(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_char_t const* format, ...); - -#ifdef TB_CONFIG_TYPE_HAVE_FLOAT -/*! writ the xml attribute for float value - * - * @param writer the xml writer - * @param name the xml attribute name - * @param value the xml attribute value - */ -tb_void_t tb_xml_writer_attributes_float(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_float_t value); - -/*! writ the xml attribute for double value - * - * @param writer the xml writer - * @param name the xml attribute name - * @param value the xml attribute value - */ -tb_void_t tb_xml_writer_attributes_double(tb_xml_writer_ref_t writer, tb_char_t const* name, tb_double_t value); -#endif - -/* ////////////////////////////////////////////////////////////////////////////////////// - * extern - */ -__tb_extern_c_leave__ - -#endif diff --git a/core/src/tbox/src/tbox/xml/xml.h b/core/src/tbox/src/tbox/xml/xml.h deleted file mode 100644 index 0fb66a0ed..000000000 --- a/core/src/tbox/src/tbox/xml/xml.h +++ /dev/null @@ -1,37 +0,0 @@ -/*!The Treasure Box Library - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (C) 2009 - 2017, TBOOX Open Source Group. - * - * @author ruki - * @file xml.h - * @defgroup xml - * - */ -#ifndef TB_XML_H -#define TB_XML_H - -/* ////////////////////////////////////////////////////////////////////////////////////// - * includes - */ -#include "prefix.h" -#include "node.h" -#include "reader.h" -#include "writer.h" - -#endif |
