static void AppendFrameToC(StringBuilder cSrc, StringBuilder cArr, RenderedFrame frame, int minRectSize, int maxRectCount, ref int estBinSize) { /* * format of the rects data is as follows: * - first two bytes are the screen and rectangle colors * - following that are 1..n rectangles: * - 5 bytes per rectangle, with x,y,w,h each with 9 bit and 4 bit flags * - like so: ABCDxxxx xxxxxyyy yyyyyyww wwwwwwwh hhhhhhhh * - flag A indicates that this is the last rectangle, and following it is the start of a new frame * - flags BCD are not used * - end condition: screen and rect color are equal */ // prepare rectangle list: sort by size descending, then filter out all rectangles below the minimum size List <Rectangle> rects = frame.Rectangles .OrderByDescending((r) => r.Width * r.Height) .Where((r) => (r.Width * r.Height) > minRectSize) .Take(maxRectCount) .ToList(); // prepare member name and add pointer to c array string memberName = "rd_" + frame.Comment; cArr.Append(memberName).AppendLine(","); // write start: comment, then screen color (secondary) and rectangle color (primary) cSrc.Append(@$ "/* {frame.Comment} ({rects.Count} rects) */ const u8 {memberName}[] = {{
void SetFlag(u8 mask, bool value) { RawInfo &= Convert.ToByte((~mask) & 0xFF); if (value) { RawInfo |= mask; } }
public void Write(BinaryWriter bw) { u32 val = Value; while (val >= 0x80) { u8 b = (u8)(val | 0x80); bw.Write(b); val >>= 7; } bw.Write((u8)(val & 0xFF)); }
public u32 Length() { u32 val = Value; u32 len = 1; while (val >= 0x80) { u8 b = (u8)(val | 0x80); val >>= 7; len++; } return(len); }
public void Read(BinaryReader br) { int val = 0; int shift = 0; while (shift < (5 * 7)) { u8 b = br.ReadByte(); val |= ((b & 0x7F) << shift); shift += 7; if ((b & 0x80) == 0) { break; } } Value = (u32)val; }
/* ** Return TRUE if the given SQL string ends in a semicolon. ** ** Special handling is require for CREATE TRIGGER statements. ** Whenever the CREATE TRIGGER keywords are seen, the statement ** must end with ";END;". ** ** This implementation uses a state machine with 7 states: ** ** (0) START At the beginning or end of an SQL statement. This routine ** returns 1 if it ends in the START state and 0 if it ends ** in any other state. ** ** (1) NORMAL We are in the middle of statement which ends with a single ** semicolon. ** ** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** ** (3) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** ** (4) TRIGGER We are in the middle of a trigger definition that must be ** ended by a semicolon, the keyword END, and another semicolon. ** ** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at ** the end of a trigger definition. ** ** (6) END We've seen the ";END" of the ";END;" that occurs at the end ** of a trigger difinition. ** ** Transitions between states above are determined by tokens extracted ** from the input. The following tokens are significant: ** ** (0) tkSEMI A semicolon. ** (1) tkWS Whitespace ** (2) tkOTHER Any other SQL token. ** (3) tkEXPLAIN The "explain" keyword. ** (4) tkCREATE The "create" keyword. ** (5) tkTEMP The "temp" or "temporary" keyword. ** (6) tkTRIGGER The "trigger" keyword. ** (7) tkEND The "end" keyword. ** ** Whitespace never causes a state transition and is always ignored. ** ** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ public static int sqlite3_complete(string zSql) { int state = 0; /* Current state, using numbers defined in header comment */ int token; /* Value of the next token */ #if !SQLITE_OMIT_TRIGGER /* A complex statement machine used to detect the end of a CREATE TRIGGER ** statement. This is the normal case. */ u8[][] trans = new u8[][] { /* Token: */ /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ /* 0 START: */ new u8[] { 0, 0, 1, 2, 3, 1, 1, 1, }, /* 1 NORMAL: */ new u8[] { 0, 1, 1, 1, 1, 1, 1, 1, }, /* 2 EXPLAIN: */ new u8[] { 0, 2, 2, 1, 3, 1, 1, 1, }, /* 3 CREATE: */ new u8[] { 0, 3, 1, 1, 1, 3, 4, 1, }, /* 4 TRIGGER: */ new u8[] { 5, 4, 4, 4, 4, 4, 4, 4, }, /* 5 SEMI: */ new u8[] { 5, 5, 4, 4, 4, 4, 4, 6, }, /* 6 END: */ new u8[] { 0, 6, 4, 4, 4, 4, 4, 4, }, };
int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
bool GetFlag(u8 mask) { return((RawInfo & mask) != 0); }
/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** ** $Id: complete.c,v 1.8 2009/04/28 04:46:42 drh Exp $ ** ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** $Header$ ************************************************************************* */ //#include "sqliteInt.h" #if !SQLITE_OMIT_COMPLETE /* ** This is defined in tokenize.c. We just have to import the definition. */ #if !SQLITE_AMALGAMATION #if SQLITE_ASCII //extern const char sqlite3IsAsciiIdChar[]; //#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsAsciiIdChar[c-0x20])) static bool IdChar(u8 C) { u8 c; return(((c = C) & 0x80) != 0 || (c > 0x1f && sqlite3IsAsciiIdChar[c - 0x20])); }
/* ** Return TRUE if the given SQL string ends in a semicolon. ** ** Special handling is require for CREATE TRIGGER statements. ** Whenever the CREATE TRIGGER keywords are seen, the statement ** must end with ";END;". ** ** This implementation uses a state machine with 8 states: ** ** (0) INVALID We have not yet seen a non-whitespace character. ** ** (1) START At the beginning or end of an SQL statement. This routine ** returns 1 if it ends in the START state and 0 if it ends ** in any other state. ** ** (2) NORMAL We are in the middle of statement which ends with a single ** semicolon. ** ** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** ** (4) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** ** (5) TRIGGER We are in the middle of a trigger definition that must be ** ended by a semicolon, the keyword END, and another semicolon. ** ** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at ** the end of a trigger definition. ** ** (7) END We've seen the ";END" of the ";END;" that occurs at the end ** of a trigger difinition. ** ** Transitions between states above are determined by tokens extracted ** from the input. The following tokens are significant: ** ** (0) tkSEMI A semicolon. ** (1) tkWS Whitespace. ** (2) tkOTHER Any other SQL token. ** (3) tkEXPLAIN The "explain" keyword. ** (4) tkCREATE The "create" keyword. ** (5) tkTEMP The "temp" or "temporary" keyword. ** (6) tkTRIGGER The "trigger" keyword. ** (7) tkEND The "end" keyword. ** ** Whitespace never causes a state transition and is always ignored. ** This means that a SQL string of all whitespace is invalid. ** ** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ static public int sqlite3_complete(string zSql) { int state = 0; /* Current state, using numbers defined in header comment */ int token; /* Value of the next token */ #if !SQLITE_OMIT_TRIGGER /* A complex statement machine used to detect the end of a CREATE TRIGGER ** statement. This is the normal case. */ u8[][] trans = new u8[][] { /* Token: */ /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ /* 0 INVALID: */ new u8[] { 1, 0, 2, 3, 4, 2, 2, 2, }, /* 1 START: */ new u8[] { 1, 1, 2, 3, 4, 2, 2, 2, }, /* 2 NORMAL: */ new u8[] { 1, 2, 2, 2, 2, 2, 2, 2, }, /* 3 EXPLAIN: */ new u8[] { 1, 3, 3, 2, 4, 2, 2, 2, }, /* 4 CREATE: */ new u8[] { 1, 4, 2, 2, 2, 4, 5, 2, }, /* 5 TRIGGER: */ new u8[] { 6, 5, 5, 5, 5, 5, 5, 5, }, /* 6 SEMI: */ new u8[] { 6, 6, 5, 5, 5, 5, 5, 7, }, /* 7 END: */ new u8[] { 1, 7, 5, 5, 5, 5, 5, 5, }, }; #else /* If triggers are not supported by this compile then the statement machine ** used to detect the end of a statement is much simplier */ u8[][] trans = new u8[][] { /* Token: */ /* State: ** SEMI WS OTHER */ /* 0 INVALID: */ new u8[] { 1, 0, 2, }, /* 1 START: */ new u8[] { 1, 1, 2, }, /* 2 NORMAL: */ new u8[] { 1, 2, 2, }, }; #endif // * SQLITE_OMIT_TRIGGER */ int zIdx = 0; while (zIdx < zSql.Length) { switch (zSql[zIdx]) { case ';': { /* A semicolon */ token = tkSEMI; break; } case ' ': case '\r': case '\t': case '\n': case '\f': { /* White space is ignored */ token = tkWS; break; } case '/': { /* C-style comments */ if (zSql[zIdx + 1] != '*') { token = tkOTHER; break; } zIdx += 2; while (zIdx < zSql.Length && zSql[zIdx] != '*' || zIdx < zSql.Length - 1 && zSql[zIdx + 1] != '/') { zIdx++; } if (zIdx == zSql.Length) { return(0); } zIdx++; token = tkWS; break; } case '-': { /* SQL-style comments from "--" to end of line */ if (zSql[zIdx + 1] != '-') { token = tkOTHER; break; } while (zIdx < zSql.Length && zSql[zIdx] != '\n') { zIdx++; } if (zIdx == zSql.Length) { return(state == 1 ? 1 : 0); //if( *zSql==0 ) return state==1; } token = tkWS; break; } case '[': { /* Microsoft-style identifiers in [...] */ zIdx++; while (zIdx < zSql.Length && zSql[zIdx] != ']') { zIdx++; } if (zIdx == zSql.Length) { return(0); } token = tkOTHER; break; } case '`': /* Grave-accent quoted symbols used by MySQL */ case '"': /* single- and double-quoted strings */ case '\'': { int c = zSql[zIdx]; zIdx++; while (zIdx < zSql.Length && zSql[zIdx] != c) { zIdx++; } if (zIdx == zSql.Length) { return(0); } token = tkOTHER; break; } default: { #if SQLITE_EBCDIC unsigned char c; #endif if (IdChar((u8)zSql[zIdx])) { /* Keywords and unquoted identifiers */ int nId; for (nId = 1; (zIdx + nId) < zSql.Length && IdChar((u8)zSql[zIdx + nId]); nId++) { } #if SQLITE_OMIT_TRIGGER token = tkOTHER; #else switch (zSql[zIdx]) { case 'c': case 'C': { if (nId == 6 && sqlite3StrNICmp(zSql, zIdx, "create", 6) == 0) { token = tkCREATE; } else { token = tkOTHER; } break; } case 't': case 'T': { if (nId == 7 && sqlite3StrNICmp(zSql, zIdx, "trigger", 7) == 0) { token = tkTRIGGER; } else if (nId == 4 && sqlite3StrNICmp(zSql, zIdx, "temp", 4) == 0) { token = tkTEMP; } else if (nId == 9 && sqlite3StrNICmp(zSql, zIdx, "temporary", 9) == 0) { token = tkTEMP; } else { token = tkOTHER; } break; } case 'e': case 'E': { if (nId == 3 && sqlite3StrNICmp(zSql, zIdx, "end", 3) == 0) { token = tkEND; } else #if !SQLITE_OMIT_EXPLAIN if (nId == 7 && sqlite3StrNICmp(zSql, zIdx, "explain", 7) == 0) { token = tkEXPLAIN; } else #endif { token = tkOTHER; } break; } default: { token = tkOTHER; break; } } #endif // * SQLITE_OMIT_TRIGGER */ zIdx += nId - 1; } else { /* Operators and special symbols */ token = tkOTHER; } break; } } state = trans[state][token]; zIdx++; } return((state == 1) ? 1 : 0);//return state==1; }
/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** SQLITE_SOURCE_ID: 2010-01-05 15:30:36 28d0d7710761114a44a1a3a425a6883c661f06e7 ** ** $Header$ ************************************************************************* */ //#include "sqliteInt.h" #if !SQLITE_OMIT_COMPLETE /* ** This is defined in tokenize.c. We just have to import the definition. */ #if !SQLITE_AMALGAMATION #if SQLITE_ASCII //#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0) static bool IdChar(u8 C) { return((sqlite3CtypeMap[(char)C] & 0x46) != 0); }
/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** SQLITE_SOURCE_ID: 2010-08-23 18:52:01 42537b60566f288167f1b5864a5435986838e3a3 ** ************************************************************************* */ //#include "sqliteInt.h" #if !SQLITE_OMIT_COMPLETE /* ** This is defined in tokenize.c. We just have to import the definition. */ #if !SQLITE_AMALGAMATION #if !NO_SQLITE_ASCII //#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0) static bool IdChar( u8 C ) { return ( sqlite3CtypeMap[(char)C] & 0x46 ) != 0; }
/* ** Change the value of the P5 operand for the most recently ** added operation. */ void sqlite3VdbeChangeP5(Vdbe *p, u8 val){ assert( p!=0 ); if( p->aOp ){ assert( p->nOp>0 ); p->aOp[p->nOp-1].p5 = val; } }
/* ** This function returns a pointer to a nul-terminated string in memory ** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the ** string contains a copy of zRawSql but with host parameters expanded to ** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, ** then the returned string holds a copy of zRawSql with "-- " prepended ** to each line of text. ** ** The calling function is responsible for making sure the memory returned ** is eventually freed. ** ** ALGORITHM: Scan the input string looking for host parameters in any of ** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within ** string literals, quoted identifier names, and comments. For text forms, ** the host parameter index is found by scanning the perpared ** statement for the corresponding OP_Variable opcode. Once the host ** parameter index is known, locate the value in p->aVar[]. Then render ** the value as a literal in place of the host parameter name. */ private static string sqlite3VdbeExpandSql( Vdbe p, /* The prepared statement being evaluated */ string zRawSql /* Raw text of the SQL statement */ ) { sqlite3 db; /* The database connection */ int idx = 0; /* Index of a host parameter */ int nextIndex = 1; /* Index of next ? host parameter */ int n; /* Length of a token prefix */ int nToken = 0; /* Length of the parameter token */ int i; /* Loop counter */ Mem pVar; /* Value of a host parameter */ StrAccum _out = new StrAccum(1000); /* Accumulate the _output here */ int izRawSql = 0; db = p.db; sqlite3StrAccumInit(_out, null, 100, db.aLimit[SQLITE_LIMIT_LENGTH]); _out.db = db; if (db.vdbeExecCnt > 1) { while (izRawSql < zRawSql.Length) { //string zStart = zRawSql; while (zRawSql[izRawSql++] != '\n' && izRawSql < zRawSql.Length) { ; } sqlite3StrAccumAppend(_out, "-- ", 3); sqlite3StrAccumAppend(_out, zRawSql, (int)izRawSql); //zRawSql - zStart ); } } else { while (izRawSql < zRawSql.Length) { n = findNextHostParameter(zRawSql, izRawSql, ref nToken); Debug.Assert(n > 0); sqlite3StrAccumAppend(_out, zRawSql.Substring(izRawSql, n), n); izRawSql += n; Debug.Assert(izRawSql < zRawSql.Length || nToken == 0); if (nToken == 0) { break; } if (zRawSql[izRawSql] == '?') { if (nToken > 1) { Debug.Assert(sqlite3Isdigit(zRawSql[izRawSql + 1])); sqlite3GetInt32(zRawSql, izRawSql + 1, ref idx); } else { idx = nextIndex; } } else { Debug.Assert(zRawSql[izRawSql] == ':' || zRawSql[izRawSql] == '$' || zRawSql[izRawSql] == '@'); testcase(zRawSql[izRawSql] == ':'); testcase(zRawSql[izRawSql] == '$'); testcase(zRawSql[izRawSql] == '@'); idx = sqlite3VdbeParameterIndex(p, zRawSql.Substring(izRawSql, nToken), nToken); Debug.Assert(idx > 0); } izRawSql += nToken; nextIndex = idx + 1; Debug.Assert(idx > 0 && idx <= p.nVar); pVar = p.aVar[idx - 1]; if ((pVar.flags & MEM_Null) != 0) { sqlite3StrAccumAppend(_out, "NULL", 4); } else if ((pVar.flags & MEM_Int) != 0) { sqlite3XPrintf(_out, "%lld", pVar.u.i); } else if ((pVar.flags & MEM_Real) != 0) { sqlite3XPrintf(_out, "%!.15g", pVar.r); } else if ((pVar.flags & MEM_Str) != 0) { #if !SQLITE_OMIT_UTF16 u8 enc = ENC(db); if (enc != SQLITE_UTF8) { Mem utf8; memset(&utf8, 0, sizeof(utf8)); utf8.db = db; sqlite3VdbeMemSetStr(&utf8, pVar.z, pVar.n, enc, SQLITE_STATIC); sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); sqlite3XPrintf(_out, "'%.*q'", utf8.n, utf8.z); sqlite3VdbeMemRelease(&utf8); } else #endif { sqlite3XPrintf(_out, "'%.*q'", pVar.n, pVar.z); } } else if ((pVar.flags & MEM_Zero) != 0) { sqlite3XPrintf(_out, "zeroblob(%d)", pVar.u.nZero); } else { Debug.Assert((pVar.flags & MEM_Blob) != 0); sqlite3StrAccumAppend(_out, "x'", 2); for (i = 0; i < pVar.n; i++) { sqlite3XPrintf(_out, "%02x", pVar.zBLOB[i] & 0xff); } sqlite3StrAccumAppend(_out, "'", 1); } } } return(sqlite3StrAccumFinish(_out)); }
/* ** Return TRUE if the given SQL string ends in a semicolon. ** ** Special handling is require for CREATE TRIGGER statements. ** Whenever the CREATE TRIGGER keywords are seen, the statement ** must end with ";END;". ** ** This implementation uses a state machine with 8 states: ** ** (0) INVALID We have not yet seen a non-whitespace character. ** ** (1) START At the beginning or end of an SQL statement. This routine ** returns 1 if it ends in the START state and 0 if it ends ** in any other state. ** ** (2) NORMAL We are in the middle of statement which ends with a single ** semicolon. ** ** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** ** (4) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** ** (5) TRIGGER We are in the middle of a trigger definition that must be ** ended by a semicolon, the keyword END, and another semicolon. ** ** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at ** the end of a trigger definition. ** ** (7) END We've seen the ";END" of the ";END;" that occurs at the end ** of a trigger difinition. ** ** Transitions between states above are determined by tokens extracted ** from the input. The following tokens are significant: ** ** (0) tkSEMI A semicolon. ** (1) tkWS Whitespace. ** (2) tkOTHER Any other SQL token. ** (3) tkEXPLAIN The "explain" keyword. ** (4) tkCREATE The "create" keyword. ** (5) tkTEMP The "temp" or "temporary" keyword. ** (6) tkTRIGGER The "trigger" keyword. ** (7) tkEND The "end" keyword. ** ** Whitespace never causes a state transition and is always ignored. ** This means that a SQL string of all whitespace is invalid. ** ** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ static public int sqlite3_complete( string zSql ) { int state = 0; /* Current state, using numbers defined in header comment */ int token; /* Value of the next token */ #if !SQLITE_OMIT_TRIGGER /* A complex statement machine used to detect the end of a CREATE TRIGGER ** statement. This is the normal case. */ u8[][] trans = new u8[][] { /* Token: */ /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ /* 0 INVALID: */ new u8[]{ 1, 0, 2, 3, 4, 2, 2, 2, }, /* 1 START: */ new u8[]{ 1, 1, 2, 3, 4, 2, 2, 2, }, /* 2 NORMAL: */ new u8[]{ 1, 2, 2, 2, 2, 2, 2, 2, }, /* 3 EXPLAIN: */ new u8[]{ 1, 3, 3, 2, 4, 2, 2, 2, }, /* 4 CREATE: */ new u8[]{ 1, 4, 2, 2, 2, 4, 5, 2, }, /* 5 TRIGGER: */ new u8[]{ 6, 5, 5, 5, 5, 5, 5, 5, }, /* 6 SEMI: */ new u8[]{ 6, 6, 5, 5, 5, 5, 5, 7, }, /* 7 END: */ new u8[]{ 1, 7, 5, 5, 5, 5, 5, 5, }, }; #else /* If triggers are not supported by this compile then the statement machine ** used to detect the end of a statement is much simplier */ u8[][] trans = new u8[][] { /* Token: */ /* State: ** SEMI WS OTHER */ /* 0 INVALID: */new u8[] { 1, 0, 2, }, /* 1 START: */new u8[] { 1, 1, 2, }, /* 2 NORMAL: */new u8[] { 1, 2, 2, }, }; #endif // * SQLITE_OMIT_TRIGGER */ int zIdx = 0; while ( zIdx < zSql.Length ) { switch ( zSql[zIdx] ) { case ';': { /* A semicolon */ token = tkSEMI; break; } case ' ': case '\r': case '\t': case '\n': case '\f': { /* White space is ignored */ token = tkWS; break; } case '/': { /* C-style comments */ if ( zSql[zIdx + 1] != '*' ) { token = tkOTHER; break; } zIdx += 2; while ( zIdx < zSql.Length && zSql[zIdx] != '*' || zIdx < zSql.Length - 1 && zSql[zIdx + 1] != '/' ) { zIdx++; } if ( zIdx == zSql.Length ) return 0; zIdx++; token = tkWS; break; } case '-': { /* SQL-style comments from "--" to end of line */ if ( zSql[zIdx + 1] != '-' ) { token = tkOTHER; break; } while ( zIdx < zSql.Length && zSql[zIdx] != '\n' ) { zIdx++; } if ( zIdx == zSql.Length ) return state == 1 ? 1 : 0;//if( *zSql==0 ) return state==1; token = tkWS; break; } case '[': { /* Microsoft-style identifiers in [...] */ zIdx++; while ( zIdx < zSql.Length && zSql[zIdx] != ']' ) { zIdx++; } if ( zIdx == zSql.Length ) return 0; token = tkOTHER; break; } case '`': /* Grave-accent quoted symbols used by MySQL */ case '"': /* single- and double-quoted strings */ case '\'': { int c = zSql[zIdx]; zIdx++; while ( zIdx < zSql.Length && zSql[zIdx] != c ) { zIdx++; } if ( zIdx == zSql.Length ) return 0; token = tkOTHER; break; } default: { //#if SQLITE_EBCDIC // unsigned char c; //#endif if ( IdChar( (u8)zSql[zIdx] ) ) { /* Keywords and unquoted identifiers */ int nId; for ( nId = 1; ( zIdx + nId ) < zSql.Length && IdChar( (u8)zSql[zIdx + nId] ); nId++ ) { } #if SQLITE_OMIT_TRIGGER token = tkOTHER; #else switch ( zSql[zIdx] ) { case 'c': case 'C': { if ( nId == 6 && sqlite3StrNICmp( zSql, zIdx, "create", 6 ) == 0 ) { token = tkCREATE; } else { token = tkOTHER; } break; } case 't': case 'T': { if ( nId == 7 && sqlite3StrNICmp( zSql, zIdx, "trigger", 7 ) == 0 ) { token = tkTRIGGER; } else if ( nId == 4 && sqlite3StrNICmp( zSql, zIdx, "temp", 4 ) == 0 ) { token = tkTEMP; } else if ( nId == 9 && sqlite3StrNICmp( zSql, zIdx, "temporary", 9 ) == 0 ) { token = tkTEMP; } else { token = tkOTHER; } break; } case 'e': case 'E': { if ( nId == 3 && sqlite3StrNICmp( zSql, zIdx, "end", 3 ) == 0 ) { token = tkEND; } else #if !SQLITE_OMIT_EXPLAIN if ( nId == 7 && sqlite3StrNICmp( zSql, zIdx, "explain", 7 ) == 0 ) { token = tkEXPLAIN; } else #endif { token = tkOTHER; } break; } default: { token = tkOTHER; break; } } #endif // * SQLITE_OMIT_TRIGGER */ zIdx += nId - 1; } else { /* Operators and special symbols */ token = tkOTHER; } break; } } state = trans[state][token]; zIdx++; } return ( state == 1 ) ? 1 : 0;//return state==1; }
/* ** Change the value of the P5 operand for the most recently ** added operation. */ static void sqlite3VdbeChangeP5( Vdbe p, u8 val ) { Debug.Assert( p != null ); if ( p.aOp != null ) { Debug.Assert( p.nOp > 0 ); p.aOp[p.nOp - 1].p5 = val; } }
/* ** Return a pointer to an sqlite3_value structure containing the value bound ** parameter iVar of VM v. Except, if the value is an SQL NULL, return ** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_* ** constants) to the value before returning it. ** ** The returned value must be freed by the caller using sqlite3ValueFree(). */ static sqlite3_value sqlite3VdbeGetValue( Vdbe v, int iVar, u8 aff ) { Debug.Assert( iVar > 0 ); if ( v != null ) { Mem pMem = v.aVar[iVar - 1]; if ( 0 == ( pMem.flags & MEM_Null ) ) { sqlite3_value pRet = sqlite3ValueNew( v.db ); if ( pRet != null ) { sqlite3VdbeMemCopy( (Mem)pRet, pMem ); sqlite3ValueApplyAffinity( pRet, (char)aff, SQLITE_UTF8 ); sqlite3VdbeMemStoreType( (Mem)pRet ); } return pRet; } } return null; }
/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that implements the sqlite3_complete() API. ** This code used to be part of the tokenizer.c source file. But by ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** ** $Id: complete.c,v 1.8 2009/04/28 04:46:42 drh Exp $ ** ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** $Header$ ************************************************************************* */ //#include "sqliteInt.h" #if !SQLITE_OMIT_COMPLETE /* ** This is defined in tokenize.c. We just have to import the definition. */ #if !SQLITE_AMALGAMATION #if SQLITE_ASCII //extern const char sqlite3IsAsciiIdChar[]; //#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsAsciiIdChar[c-0x20])) static bool IdChar( u8 C ) { u8 c; return ( ( c = C ) & 0x80 ) != 0 || ( c > 0x1f && sqlite3IsAsciiIdChar[c - 0x20] ); }
/* ** Return TRUE if the given SQL string ends in a semicolon. ** ** Special handling is require for CREATE TRIGGER statements. ** Whenever the CREATE TRIGGER keywords are seen, the statement ** must end with ";END;". ** ** This implementation uses a state machine with 7 states: ** ** (0) START At the beginning or end of an SQL statement. This routine ** returns 1 if it ends in the START state and 0 if it ends ** in any other state. ** ** (1) NORMAL We are in the middle of statement which ends with a single ** semicolon. ** ** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** ** (3) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** ** (4) TRIGGER We are in the middle of a trigger definition that must be ** ended by a semicolon, the keyword END, and another semicolon. ** ** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at ** the end of a trigger definition. ** ** (6) END We've seen the ";END" of the ";END;" that occurs at the end ** of a trigger difinition. ** ** Transitions between states above are determined by tokens extracted ** from the input. The following tokens are significant: ** ** (0) tkSEMI A semicolon. ** (1) tkWS Whitespace ** (2) tkOTHER Any other SQL token. ** (3) tkEXPLAIN The "explain" keyword. ** (4) tkCREATE The "create" keyword. ** (5) tkTEMP The "temp" or "temporary" keyword. ** (6) tkTRIGGER The "trigger" keyword. ** (7) tkEND The "end" keyword. ** ** Whitespace never causes a state transition and is always ignored. ** ** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ static public int sqlite3_complete( string zSql ) { int state = 0; /* Current state, using numbers defined in header comment */ int token; /* Value of the next token */ #if !SQLITE_OMIT_TRIGGER /* A complex statement machine used to detect the end of a CREATE TRIGGER ** statement. This is the normal case. */ u8[][] trans = new u8[][] { /* Token: */ /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ /* 0 START: */ new u8[] { 0, 0, 1, 2, 3, 1, 1, 1, }, /* 1 NORMAL: */ new u8[]{ 0, 1, 1, 1, 1, 1, 1, 1, }, /* 2 EXPLAIN: */ new u8[]{ 0, 2, 2, 1, 3, 1, 1, 1, }, /* 3 CREATE: */ new u8[]{ 0, 3, 1, 1, 1, 3, 4, 1, }, /* 4 TRIGGER: */ new u8[]{ 5, 4, 4, 4, 4, 4, 4, 4, }, /* 5 SEMI: */ new u8[]{ 5, 5, 4, 4, 4, 4, 4, 6, }, /* 6 END: */ new u8[]{ 0, 6, 4, 4, 4, 4, 4, 4, }, };
public bool Read(BinaryReader br) { u8 prefix = br.ReadByte(); if (prefix != PREFIX_SIZE) { return(false); } EncodedInt encSize = new EncodedInt(); encSize.Read(br); u32 size_expected = encSize.Value; u32 size_read = 0; bool reading_items = false; prefix = br.ReadByte(); size_read++; switch (prefix) { case PREFIX_ITEM_ID: reading_items = true; break; case PREFIX_CLIENT_KEY: break; default: return(false); } if (reading_items) { EncodedInt encId = new EncodedInt(); encId.Read(br); item_id = encId.Value; size_read += encId.Length(); if (size_read == size_expected) { return(true); } prefix = br.ReadByte(); size_read++; if (prefix != PREFIX_ITEM_NAME) { return(false); } } EncodedInt encName = new EncodedInt(); encName.Read(br); name = DecodeString(br, encName.Value); size_read += encName.Value + encName.Length(); if (size_read == size_expected) { return(true); } prefix = br.ReadByte(); size_read++; if (reading_items) { if (prefix != PREFIX_ITEM_VALUE) { return(false); } } else if (prefix != PREFIX_CLIENT_VAL) { return(false); } EncodedInt encValue = new EncodedInt(); encValue.Read(br); value = DecodeString(br, encValue.Value); size_read += encValue.Value + encValue.Length();; if (size_read != size_expected) { return(false); } return(true); }