private static void CallCollNeeded(Context ctx, TEXTENCODE encode, string name) { Debug.Assert(ctx.CollNeeded == null || ctx.CollNeeded16 == null); if (ctx.CollNeeded != null) { string external = name; if (external == null) { return; } ctx.CollNeeded(ctx.CollNeededArg, ctx, encode, external); C._tagfree(ctx, ref external); } #if !OMIT_UTF16 if (ctx.CollNeeded16 != null) { Mem tmp = Mem_New(ctx); Mem_SetStr(tmp, -1, name, TEXTENCODE.UTF8, DESTRUCTOR.STATIC); string external = Mem_Text(tmp, TEXTENCODE.UTF16NATIVE); if (external != null) { ctx.CollNeeded16(ctx.CollNeededArg, ctx, Context.CTXENCODE(ctx), external); } Mem_Free(ref tmp); } #endif }
public static void ValueSetStr(Mem mem, int n, string z, TEXTENCODE encode, Action <object> del) { if (mem != null) { MemSetStr(mem, z, n, encode, del); } }
static RC BindText(Vdbe p, int i, string z, int n, Action <string> del, TEXTENCODE encoding) { RC rc = VdbeUnbind(p, i); if (rc == RC.OK) { if (z != null) { Mem var = p.Vars[i - 1]; rc = MemSetStr(var, z, n, encoding, del); if (rc == RC.OK && encoding != 0) { rc = ChangeEncoding(var, E.CTXENCODE(p.Ctx)); } SysEx.Error(p.Ctx, rc, 0); rc = SysEx.ApiExit(p.Ctx, rc); } MutexEx.Leave(p.Ctx.Mutex); } else if (del != null) { del(z); } return(rc); }
const int FUNC_PERFECT_MATCH = 6; // The score for a perfect match static int MatchQuality(FuncDef p, int args, TEXTENCODE encode) { // nArg of -2 is a special case if (args == -2) { return(p.Func == null && p.Step == null ? 0 : FUNC_PERFECT_MATCH); } // Wrong number of arguments means "no match" if (p.Args != args && p.Args >= 0) { return(0); } // Give a better score to a function with a specific number of arguments than to function that accepts any number of arguments. int match = (p.Args == args ? 4 : 1); // Bonus points if the text encoding matches if (encode == p.PrefEncode) { match += 2; // Exact encoding match } else if ((encode & p.PrefEncode & (TEXTENCODE)2) != 0) { match += 1; // Both are UTF16, but with different byte orders } return(match); }
public static RC MemHandleBom(Mem mem) { RC rc = RC.OK; TEXTENCODE bom = 0; Debug.Assert(mem.N >= 0); if (mem.N > 1) { byte[] b01 = new byte[2]; Encoding.Unicode.GetBytes(mem.Z, 0, 1, b01, 0); if (b01[0] == 0xFE && b01[1] == 0xFF) { bom = TEXTENCODE.UTF16BE; } if (b01[0] == 0xFF && b01[1] == 0xFE) { bom = TEXTENCODE.UTF16LE; } } if (bom != 0) { rc = MemMakeWriteable(mem); if (rc == RC.OK) { mem.N -= 2; Debugger.Break(); // TODO - //memmove(pMem.z, pMem.z[2], pMem.n); //pMem.z[pMem.n] = '\0'; //pMem.z[pMem.n+1] = '\0'; mem.Flags |= MEM.Term; mem.Encode = bom; } } return(rc); }
// The following routines are used by user-defined functions to specify the function result. // // The setStrOrError() funtion calls sqlite3VdbeMemSetStr() to store the result as a string or blob but if the string or blob is too large, it // then sets the error code to SQLITE_TOOBIG static void SetResultStrOrError(FuncContext fctx, string z, int o, int n, TEXTENCODE encode, Action del) { if (Vdbe.MemSetStr(fctx.S, z, o, n, encode, del) == RC.TOOBIG) { Vdbe.Result_ErrorOverflow(fctx); } }
static int ValueBytes(Mem mem, TEXTENCODE encode) { if ((mem.Flags & MEM.Blob) != 0 || ValueText(mem, encode) != null) { return((mem.Flags & MEM.Zero) != 0 ? mem.N + mem.u.Zeros : (mem.Z == null ? mem.Z_.Length : mem.N)); } return(0); }
public static RC MemStringify(Mem mem, TEXTENCODE encode) { MEM f = mem.Flags; Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((f & MEM.Zero) == 0); Debug.Assert((f & (MEM.Str | MEM.Blob)) == 0); Debug.Assert((f & (MEM.Int | MEM.Real)) != 0); Debug.Assert((mem.Flags & MEM.RowSet) == 0); //: Debug.Assert(C._HASALIGNMENT8(mem)); const int bytes = 32; if (MemGrow(mem, bytes, false) != 0) { return(RC.NOMEM); } // For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8 string representation of the value. Then, if the required encoding // is UTF-16le or UTF-16be do a translation. // FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. if ((f & MEM.Int) != 0) { mem.Z = mem.u.I.ToString(); //: __snprintf(mem->Z, bytes, "%lld", mem->u.I); } else { Debug.Assert((f & MEM.Real) != 0); if (double.IsNegativeInfinity(mem.R)) { mem.Z = "-Inf"; } else if (double.IsInfinity(mem.R)) { mem.Z = "Inf"; } else if (double.IsPositiveInfinity(mem.R)) { mem.Z = "+Inf"; } else if (mem.R.ToString(CultureInfo.InvariantCulture).Contains(".")) { mem.Z = mem.R.ToString(CultureInfo.InvariantCulture).ToLower(); //: __snprintf(mem->Z, bytes, "%!.15g", mem->R); } else { mem.Z = mem.R.ToString(CultureInfo.InvariantCulture) + ".0"; } } mem.N = mem.Z.Length; mem.Encode = TEXTENCODE.UTF8; mem.Flags |= MEM.Str | MEM.Term; ChangeEncoding(mem, encode); return(RC.OK); }
public static RC MemSetStr(Mem mem, byte[] z, int offset, int n, TEXTENCODE encode, Action <object> del) { Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((mem.Flags & MEM.RowSet) == 0); // If z is a NULL pointer, set pMem to contain an SQL NULL. if (z == null || z.Length < offset) { MemSetNull(mem); return(RC.OK); } int limit = (mem.Ctx != null ? mem.Ctx.Limits[(int)LIMIT.LENGTH] : CORE_MAX_LENGTH); // Maximum allowed string or blob size MEM flags = (encode == 0 ? MEM.Blob : MEM.Str); // New value for pMem->flags int bytes = n; // New value for pMem->n if (bytes < 0) { Debug.Assert(encode != 0); if (encode == TEXTENCODE.UTF8) { for (bytes = 0; bytes <= limit && bytes < z.Length - offset && z[offset + bytes] != 0; bytes++) { } } else { for (bytes = 0; bytes <= limit && z[bytes + offset] != 0 || z[offset + bytes + 1] != 0; bytes += 2) { } } } // The following block sets the new values of Mem.z and Mem.xDel. It also sets a flag in local variable "flags" to indicate the memory // management (one of MEM_Dyn or MEM_Static). Debug.Assert(encode == 0); { mem.Z = null; mem.Z_ = C._alloc(n); Buffer.BlockCopy(z, offset, mem.Z_, 0, n); } mem.N = bytes; mem.Flags = MEM.Blob | MEM.Term; mem.Encode = (encode == 0 ? TEXTENCODE.UTF8 : encode); mem.Type = (encode == 0 ? TYPE.BLOB : TYPE.TEXT); #if !OMIT_UTF16 if (mem.Encode != TEXTENCODE.UTF8 && MemHandleBom(mem) != 0) { return(RC.NOMEM); } #endif return(bytes > limit ? RC.TOOBIG : RC.OK); }
public string Utf8to16(Context ctx, TEXTENCODE encode, string z, int n, ref int out_) { Mem m = new Mem(); m.Ctx = ctx; MemSetStr(m, z, n, TEXTENCODE.UTF8, C.DESTRUCTOR_STATIC); if (MemTranslate(m, encode) != RC.OK) { Debug.Assert(ctx.MallocFailed); return(null); } //Debug.Assert(m.Z == m.zMalloc); out_ = m.N; return(m.Z); }
public static CollSeq FindCollSeq(Context ctx, TEXTENCODE encode, string name, bool create) { CollSeq[] colls; if (name != null) { colls = FindCollSeqEntry(ctx, name, create); } else { colls = new CollSeq[(int)encode]; colls[(int)encode - 1] = ctx.DefaultColl; } Debug.Assert((int)TEXTENCODE.UTF8 == 1 && (int)TEXTENCODE.UTF16LE == 2 && (int)TEXTENCODE.UTF16BE == 3); Debug.Assert(encode >= TEXTENCODE.UTF8 && encode <= TEXTENCODE.UTF16BE); return(colls != null ? colls[(int)encode - 1] : null); }
public static string Utf16to8(Context ctx, string z, int bytes, TEXTENCODE encode) { Debugger.Break(); // TODO - Mem m = null; // Pool.Allocate_Mem(); // memset(&m, 0, sizeof(m)); // m.db = db; // sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC); // sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); // if( db.mallocFailed !=0{ // sqlite3VdbeMemRelease(&m); // m.z = 0; // } // Debug.Assert( (m.flags & MEM_Term)!=0 || db.mallocFailed !=0); // Debug.Assert( (m.flags & MEM_Str)!=0 || db.mallocFailed !=0); Debug.Assert((m.Flags & MEM.Dyn) != 0 || ctx.MallocFailed); Debug.Assert(m.Z != null || ctx.MallocFailed); return(m.Z); }
public Mem(Context db, string z, double r, int i, int n, MEM flags, TYPE type, TEXTENCODE encode #if DEBUG , Mem scopyFrom, object filler #endif ) { Ctx = db; Z = z; R = r; u.I = i; N = n; Flags = flags; #if DEBUG ScopyFrom = scopyFrom; Filler = filler; #endif Type = type; Encode = encode; }
public static RC ChangeEncoding(Mem mem, TEXTENCODE newEncode) { Debug.Assert((mem.Flags & MEM.RowSet) == 0); Debug.Assert(newEncode == TEXTENCODE.UTF8 || newEncode == TEXTENCODE.UTF16LE || newEncode == TEXTENCODE.UTF16BE); if ((mem.Flags & MEM.Str) == 0 || mem.Encode == newEncode) { if (mem.Z == null && mem.Z_ != null) mem.Z = Encoding.UTF8.GetString(mem.Z_, 0, mem.Z_.Length); return RC.OK; } Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); #if OMIT_UTF16 return RC.ERROR; #else // MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned, then the encoding of the value may not have changed. RC rc = MemTranslate(mem, newEncode); Debug.Assert(rc == RC.OK || rc == RC.NOMEM); Debug.Assert(rc == RC.OK || mem.Encode != newEncode); Debug.Assert(rc == RC.NOMEM || mem.Encode == newEncode); return rc; #endif }
public static CollSeq GetCollSeq(Parse parse, TEXTENCODE encode, CollSeq coll, string name) { Context ctx = parse.Ctx; CollSeq p = coll; if (p == null) { p = FindCollSeq(ctx, encode, name, false); } if (p == null || p.Cmp == null) { // No collation sequence of this type for this encoding is registered. Call the collation factory to see if it can supply us with one. CallCollNeeded(ctx, encode, name); p = FindCollSeq(ctx, encode, name, false); } Debug.Assert(p == null || p.Cmp != null); if (p != null) { parse.ErrorMsg("no such collation sequence: %s", name); } return(p); }
public static string ValueText(Mem mem, TEXTENCODE encode) { if (mem == null) { return(null); } Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((encode & (TEXTENCODE)3) == (encode & ~TEXTENCODE.UTF16_ALIGNED)); Debug.Assert((mem.Flags & MEM.RowSet) == 0); if ((mem.Flags & MEM.Null) != 0) { return(null); } Debug.Assert(((int)MEM.Blob >> 3) == (int)MEM.Str); mem.Flags |= (MEM)((int)(mem.Flags & MEM.Blob) >> 3); E.ExpandBlob(mem); if ((mem.Flags & MEM.Str) != 0) { ChangeEncoding(mem, encode & ~TEXTENCODE.UTF16_ALIGNED); if ((encode & TEXTENCODE.UTF16_ALIGNED) != 0 && (1 & (mem.Z[0])) == 1) { Debug.Assert((mem.Flags & (MEM.Ephem | MEM.Static)) != 0); if (MemMakeWriteable(mem) != RC.OK) { return(null); } } MemNulTerminate(mem); // IMP: R-31275-44060 } else { Debug.Assert((mem.Flags & MEM.Blob) == 0); MemStringify(mem, encode); Debug.Assert((1 & (mem.Z[0])) == 0); } Debug.Assert(mem.Encode == (encode & ~TEXTENCODE.UTF16_ALIGNED) || mem.Ctx == null || mem.Ctx.MallocFailed); return(mem.Encode == (encode & ~TEXTENCODE.UTF16_ALIGNED) ? mem.Z : null); }
public static void sqlite3ColumnDefault(Vdbe v, Table table, int i, int regId) { Debug.Assert(table != null); if (table.Select == null) { TEXTENCODE encode = Context.CTXENCODE(v.Ctx); Column col = table.Cols[i]; v.VdbeComment("%s.%s", table.Name, col.Name); Debug.Assert(i < table.Cols.length); Mem value = new Mem(); sqlite3ValueFromExpr(v.Ctx, col.Dflt, encode, col.Affinity, ref value); if (value != null) { v.ChangeP4(-1, value, Vdbe.P4T.MEM); } #if !OMIT_FLOATING_POINT if (regId >= 0 && table.Cols[i].Affinity == AFF.REAL) { v.AddOp1(OP.RealAffinity, regId); } #endif } }
public static RC ChangeEncoding(Mem mem, TEXTENCODE newEncode) { Debug.Assert((mem.Flags & MEM.RowSet) == 0); Debug.Assert(newEncode == TEXTENCODE.UTF8 || newEncode == TEXTENCODE.UTF16LE || newEncode == TEXTENCODE.UTF16BE); if ((mem.Flags & MEM.Str) == 0 || mem.Encode == newEncode) { if (mem.Z == null && mem.Z_ != null) { mem.Z = Encoding.UTF8.GetString(mem.Z_, 0, mem.Z_.Length); } return(RC.OK); } Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); #if OMIT_UTF16 return(RC.ERROR); #else // MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned, then the encoding of the value may not have changed. RC rc = MemTranslate(mem, newEncode); Debug.Assert(rc == RC.OK || rc == RC.NOMEM); Debug.Assert(rc == RC.OK || mem.Encode != newEncode); Debug.Assert(rc == RC.NOMEM || mem.Encode == newEncode); return(rc); #endif }
public static void CTXENCODE(BContext ctx, TEXTENCODE encode) { ctx.DBs[0].Schema.Encode = encode; }
static void ValueApplyAffinity(Mem mem, char affinity, TEXTENCODE encode) { ApplyAffinity(mem, (AFF)affinity, encode); }
static RC MemSetStr(Mem mem, string z, int n, TEXTENCODE encode, Action<object> del) { return MemSetStr(mem, z, 0, n, encode, del); }
public static RC MemSetStr(Mem mem, byte[] z, int n, TEXTENCODE encode, Action<object> del) { return MemSetStr(mem, z, 0, (n >= 0 ? n : z.Length), encode, del); }
public static string Utf16to8(Context ctx, string z, int bytes, TEXTENCODE encode) { Debugger.Break(); // TODO - Mem m = null; // Pool.Allocate_Mem(); // memset(&m, 0, sizeof(m)); // m.db = db; // sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC); // sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8); // if( db.mallocFailed !=0{ // sqlite3VdbeMemRelease(&m); // m.z = 0; // } // Debug.Assert( (m.flags & MEM_Term)!=0 || db.mallocFailed !=0); // Debug.Assert( (m.flags & MEM_Str)!=0 || db.mallocFailed !=0); Debug.Assert((m.Flags & MEM.Dyn) != 0 || ctx.MallocFailed); Debug.Assert(m.Z != null || ctx.MallocFailed); return m.Z; }
public static int Atoi64(string z, out long out_, int length, TEXTENCODE encode) { if (z == null) { out_ = 0; return(1); } // get size int zIdx = 0;// string zStart; int incr = (encode == TEXTENCODE.UTF8 ? 1 : 2); if (encode == TEXTENCODE.UTF16BE) { zIdx++; } // skip leading spaces while (zIdx < length && char.IsWhiteSpace(z[zIdx])) { zIdx += incr; } // get sign of significand int neg = 0; // assume positive if (zIdx < length) { if (z[zIdx] == '-') { neg = 1; zIdx += incr; } else if (z[zIdx] == '+') { zIdx += incr; } } if (length > z.Length) { length = z.Length; } // skip leading zeros while (zIdx < length - 1 && z[zIdx] == '0') { zIdx += incr; } // Skip leading zeros. ulong u = 0; int c = 0; int i; for (i = zIdx; i < length && (c = z[i]) >= '0' && c <= '9'; i += incr) { u = u * 10 + (ulong)(c - '0'); } if (u > long.MaxValue) { out_ = long.MinValue; } else { out_ = (neg != 0 ? -(long)u : (long)u); } C.ASSERTCOVERAGE(i - zIdx == 18); C.ASSERTCOVERAGE(i - zIdx == 19); C.ASSERTCOVERAGE(i - zIdx == 20); if ((c != 0 && i < length) || i == zIdx || i - zIdx > 19 * incr) { return(1); // zNum is empty or contains non-numeric text or is longer than 19 digits (thus guaranteeing that it is too large) } else if (i - zIdx < 19 * incr) { Debug.Assert(u <= long.MaxValue); return(0); } // Less than 19 digits, so we know that it fits in 64 bits else { c = Compare2pow63(z.Substring(zIdx), incr); // zNum is a 19-digit numbers. Compare it against 9223372036854775808. if (c < 0) { Debug.Assert(u <= long.MaxValue); return(0); } // zNum is less than 9223372036854775808 so it fits else if (c > 0) { return(1); // zNum is greater than 9223372036854775808 so it overflows } else { Debug.Assert(u - 1 == long.MaxValue); Debug.Assert(out_ == long.MinValue); return(neg != 0 ? 0 : 2); } // zNum is exactly 9223372036854775808. Fits if negative. The special case 2 overflow if positive } }
static WRC ResolveExprStep(Walker walker, Expr expr) { NameContext nc = walker.u.NC; Debug.Assert(nc != null); Parse parse = nc.Parse; Debug.Assert(parse == walker.Parse); if (E.ExprHasAnyProperty(expr, EP.Resolved)) { return(WRC.Prune); } E.ExprSetProperty(expr, EP.Resolved); #if !NDEBUG if (nc.SrcList != null && nc.SrcList.Allocs > 0) { SrcList srcList = nc.SrcList; for (int i = 0; i < nc.SrcList.Srcs; i++) { Debug.Assert(srcList.Ids[i].Cursor >= 0 && srcList.Ids[i].Cursor < parse.Tabs); } } #endif switch (expr.OP) { #if ENABLE_UPDATE_DELETE_LIMIT && !OMIT_SUBQUERY // The special operator TK_ROW means use the rowid for the first column in the FROM clause. This is used by the LIMIT and ORDER BY // clause processing on UPDATE and DELETE statements. case TK.ROW: { SrcList srcList = nc.SrcList; Debug.Assert(srcList != null && srcList.Srcs == 1); SrcList.SrcListItem item = srcList.Ids[0]; expr.OP = TK.COLUMN; expr.Table = item.Table; expr.TableId = item.Cursor; expr.ColumnIdx = -1; expr.Aff = AFF.INTEGER; break; } #endif case TK.ID: // A lone identifier is the name of a column. { return(LookupName(parse, null, null, expr.u.Token, nc, expr)); } case TK.DOT: // A table name and column name: ID.ID Or a database, table and column: ID.ID.ID { string columnName; string tableName; string dbName; // if (srcList == nullptr) break; Expr right = expr.Right; if (right.OP == TK.ID) { dbName = null; tableName = expr.Left.u.Token; columnName = right.u.Token; } else { Debug.Assert(right.OP == TK.DOT); dbName = expr.Left.u.Token; tableName = right.Left.u.Token; columnName = right.Right.u.Token; } return(LookupName(parse, dbName, tableName, columnName, nc, expr)); } case TK.CONST_FUNC: case TK.FUNCTION: // Resolve function names { ExprList list = expr.x.List; // The argument list int n = (list != null ? list.Exprs : 0); // Number of arguments bool noSuchFunc = false; // True if no such function exists bool wrongNumArgs = false; // True if wrong number of arguments bool isAgg = false; // True if is an aggregate function TEXTENCODE encode = E.CTXENCODE(parse.Ctx); // The database encoding C.ASSERTCOVERAGE(expr.OP == TK.CONST_FUNC); Debug.Assert(!E.ExprHasProperty(expr, EP.xIsSelect)); string id = expr.u.Token; // The function name. int idLength = id.Length; // Number of characters in function name FuncDef def = Callback.FindFunction(parse.Ctx, id, idLength, n, encode, false); // Information about the function if (def == null) { def = Callback.FindFunction(parse.Ctx, id, idLength, -2, encode, false); if (def == null) { noSuchFunc = true; } else { wrongNumArgs = true; } } else { isAgg = (def.Func == null); } #if !OMIT_AUTHORIZATION if (def != null) { ARC auth = Auth.Check(parse, AUTH.FUNCTION, null, def.Name, null); // Authorization to use the function if (auth != ARC.OK) { if (auth == ARC.DENY) { parse.ErrorMsg("not authorized to use function: %s", def.Name); nc.Errs++; } expr.OP = TK.NULL; return(WRC.Prune); } } #endif if (isAgg && (nc.NCFlags & NC.AllowAgg) == 0) { parse.ErrorMsg("misuse of aggregate function %.*s()", idLength, id); nc.Errs++; isAgg = false; } else if (noSuchFunc && !ctx.Init.Busy) { parse.ErrorMsg("no such function: %.*s", idLength, id); nc.Errs++; } else if (wrongNumArgs) { parse.ErrorMsg("wrong number of arguments to function %.*s()", idLength, id); nc.Errs++; } if (isAgg) { nc.NCFlags &= ~NC.AllowAgg; } walker.WalkExprList(list); if (isAgg) { NameContext nc2 = nc; expr.OP = TK.AGG_FUNCTION; expr.OP2 = 0; while (nc2 != null && !expr.FunctionUsesThisSrc(nc2.SrcList)) { expr.OP2++; nc2 = nc2.Next; } if (nc2 != null) { nc2.NCFlags |= NC.HasAgg; } nc.NCFlags |= NC.AllowAgg; } // FIX ME: Compute pExpr->affinity based on the expected return type of the function return(WRC.Prune); } #if !OMIT_SUBQUERY case TK.SELECT: case TK.EXISTS: { C.ASSERTCOVERAGE(expr.OP == TK.EXISTS); goto case TK.IN; } #endif case TK.IN: { C.ASSERTCOVERAGE(expr.OP == TK.IN); if (E.ExprHasProperty(expr, EP.xIsSelect)) { int refs = nc.Refs; #if !OMIT_CHECK if ((nc.NCFlags & NC.IsCheck) != 0) { parse.ErrorMsg("subqueries prohibited in CHECK constraints"); } #endif walker.WalkSelect(expr.x.Select); Debug.Assert(nc.Refs >= refs); if (refs != nc.Refs) { E.ExprSetProperty(expr, EP.VarSelect); } } break; } #if !OMIT_CHECK case TK.VARIABLE: { if ((nc.NCFlags & NC.IsCheck) != 0) { parse.ErrorMsg("parameters prohibited in CHECK constraints"); } break; } #endif } return(parse.Errs != 0 || parse.Ctx.MallocFailed ? WRC.Abort : WRC.Continue); }
public static bool Atof(string z, ref double out_, int length, TEXTENCODE encode) { #if !OMIT_FLOATING_POINT out_ = 0.0; // Default return value, in case of an error if (string.IsNullOrEmpty(z)) return false; // getsize int zIdx = 0; int incr = (encode == TEXTENCODE.UTF8 ? 1 : 2); if (encode == TEXTENCODE.UTF16BE) zIdx++; // skip leading spaces while (zIdx < length && char.IsWhiteSpace(z[zIdx])) zIdx++; if (zIdx >= length) return false; // get sign of significand int sign = 1; // sign of significand if (z[zIdx] == '-') { sign = -1; zIdx += incr; } else if (z[zIdx] == '+') zIdx += incr; // sign * significand * (10 ^ (esign * exponent)) long s = 0; // significand int d = 0; // adjust exponent for shifting decimal point int esign = 1; // sign of exponent int e = 0; // exponent bool nonNum = true; // True exponent is either not used or is well-formed int digits = 0; // skip leading zeroes while (zIdx < z.Length && z[zIdx] == '0') { zIdx += incr; digits++; } // copy max significant digits to significand while (zIdx < length && char.IsDigit(z[zIdx]) && s < ((long.MaxValue - 9) / 10)) { s = s * 10 + (z[zIdx] - '0'); zIdx += incr; digits++; } while (zIdx < length && char.IsDigit(z[zIdx])) { zIdx += incr; digits++; d++; } if (zIdx >= length) goto do_atof_calc; // if decimal point is present if (z[zIdx] == '.') { zIdx += incr; // copy digits from after decimal to significand (decrease exponent by d to shift decimal right) while (zIdx < length && char.IsDigit(z[zIdx]) && s < ((long.MaxValue - 9) / 10)) { s = s * 10 + (z[zIdx] - '0'); zIdx += incr; digits++; d--; } while (zIdx < length && char.IsDigit(z[zIdx])) { zIdx += incr; digits++; } // skip non-significant digits } if (zIdx >= length) goto do_atof_calc; // if exponent is present if (z[zIdx] == 'e' || z[zIdx] == 'E') { zIdx += incr; nonNum = false; if (zIdx >= length) goto do_atof_calc; // get sign of exponent if (z[zIdx] == '-') { esign = -1; zIdx += incr; } else if (z[zIdx] == '+') zIdx += incr; // copy digits to exponent while (zIdx < length && char.IsDigit(z[zIdx])) { e = e * 10 + (z[zIdx] - '0'); zIdx += incr; nonNum = true; } } // skip trailing spaces if (digits != 0 && nonNum) while (zIdx < length && char.IsWhiteSpace(z[zIdx])) zIdx += incr; do_atof_calc: // adjust exponent by d, and update sign e = (e * esign) + d; if (e < 0) { esign = -1; e *= -1; } else esign = 1; // if !significand double result = 0.0; if (s == 0) result = (sign < 0 && digits != 0 ? -0.0 : 0.0); // In the IEEE 754 standard, zero is signed. Add the sign if we've seen at least one digit else { // attempt to reduce exponent if (esign > 0) while (s < (long.MaxValue / 10) && e > 0) { e--; s *= 10; } else while ((s % 10) == 0 && e > 0) { e--; s /= 10; } // adjust the sign of significand s = (sign < 0 ? -s : s); // if exponent, scale significand as appropriate and store in result. if (e != 0) { double scale = 1.0; // attempt to handle extremely small/large numbers better if (e > 307 && e < 342) { while ((e % 308) != 0) { scale *= 1.0e+1; e -= 1; } if (esign < 0) { result = s / scale; result /= 1.0e+308; } else { result = s * scale; result *= 1.0e+308; } } else if (e >= 342) result = (esign < 0 ? 0.0 * s : 1e308 * 1e308 * s); // Infinity else { // 1.0e+22 is the largest power of 10 than can be represented exactly. while ((e % 22) != 0) { scale *= 1.0e+1; e -= 1; } while (e > 0) { scale *= 1.0e+22; e -= 22; } result = (esign < 0 ? s / scale : s * scale); } } else result = (double)s; } out_ = result; // store the result return (zIdx >= length && digits > 0 && nonNum); // return true if number and no extra non-whitespace chracters after #else return !Atoi64(z, out_, length, encode); #endif }
public static void ValueSetStr(Mem mem, int n, string z, TEXTENCODE encode, Action<object> del) { if (mem != null) MemSetStr(mem, z, n, encode, del); }
public static string ValueText(Mem mem, TEXTENCODE encode) { if (mem == null) return null; Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((encode & (TEXTENCODE)3) == (encode & ~TEXTENCODE.UTF16_ALIGNED)); Debug.Assert((mem.Flags & MEM.RowSet) == 0); if ((mem.Flags & MEM.Null) != 0) return null; Debug.Assert(((int)MEM.Blob >> 3) == (int)MEM.Str); mem.Flags |= (MEM)((int)(mem.Flags & MEM.Blob) >> 3); E.ExpandBlob(mem); if ((mem.Flags & MEM.Str) != 0) { ChangeEncoding(mem, encode & ~TEXTENCODE.UTF16_ALIGNED); if ((encode & TEXTENCODE.UTF16_ALIGNED) != 0 && (1 & (mem.Z[0])) == 1) { Debug.Assert((mem.Flags & (MEM.Ephem | MEM.Static)) != 0); if (MemMakeWriteable(mem) != RC.OK) return null; } MemNulTerminate(mem); // IMP: R-31275-44060 } else { Debug.Assert((mem.Flags & MEM.Blob) == 0); MemStringify(mem, encode); Debug.Assert((1 & (mem.Z[0])) == 0); } Debug.Assert(mem.Encode == (encode & ~TEXTENCODE.UTF16_ALIGNED) || mem.Ctx == null || mem.Ctx.MallocFailed); return (mem.Encode == (encode & ~TEXTENCODE.UTF16_ALIGNED) ? mem.Z : null); }
public static void CTXENCODE(BContext ctx, TEXTENCODE encode) { ctx.DBs[0].Schema.Encode = encode; }
public static FuncDef FindFunction(Context ctx, string name, int nameLength, int args, TEXTENCODE encode, bool createFlag) { Debug.Assert(args >= -2); Debug.Assert(args >= -1 || !createFlag); Debug.Assert(encode == TEXTENCODE.UTF8 || encode == TEXTENCODE.UTF16LE || encode == TEXTENCODE.UTF16BE); int h = (char.ToLowerInvariant(name[0]) + nameLength) % ctx.Funcs.data.Length; // Hash value // First search for a match amongst the application-defined functions. FuncDef best = null; // Best match found so far int bestScore = 0; // Score of best match FuncDef p = FunctionSearch(ctx.Funcs, h, name, nameLength); while (p != null) { int score = MatchQuality(p, args, encode); if (score > bestScore) { best = p; bestScore = score; } p = p.Next; } // If no match is found, search the built-in functions. // // If the SQLITE_PreferBuiltin flag is set, then search the built-in functions even if a prior app-defined function was found. And give // priority to built-in functions. // // Except, if createFlag is true, that means that we are trying to install a new function. Whatever FuncDef structure is returned it will // have fields overwritten with new information appropriate for the new function. But the FuncDefs for built-in functions are read-only. // So we must not search for built-ins when creating a new function. if (createFlag && (best == null || (ctx.Flags & Context.FLAG.PreferBuiltin) != 0)) { FuncDefHash hash = sqlite3GlobalFunctions; bestScore = 0; p = FunctionSearch(hash, h, name, nameLength); while (p != null) { int score = MatchQuality(p, args, encode); if (score > bestScore) { best = p; bestScore = score; } p = p.Next; } } // If the createFlag parameter is true and the search did not reveal an exact match for the name, number of arguments and encoding, then add a // new entry to the hash table and return it. if (createFlag && bestScore < FUNC_PERFECT_MATCH && (best = new FuncDef()) != null) { best.Name = name; best.Args = (short)args; best.PrefEncode = encode; FuncDefInsert(ctx.Funcs, best); } return(best != null && (best.Step != null || best.Func != null || createFlag) ? best : null); }
static RC MemSetStr(Mem mem, string z, int n, TEXTENCODE encode, Action <object> del) { return(MemSetStr(mem, z, 0, n, encode, del)); }
//ctx.pDfltColl = sqlite3FindCollSeq( ctx, SQLITE_UTF8, "BINARY", 0 ); public static RC InitOne(Context ctx, int db, ref string errMsg) { Debug.Assert(db >= 0 && db < ctx.DBs.length); Debug.Assert(ctx.DBs[db].Schema != null); Debug.Assert(MutexEx.Held(ctx.Mutex)); Debug.Assert(db == 1 || ctx.DBs[db].Bt.HoldsMutex()); RC rc; int i; // zMasterSchema and zInitScript are set to point at the master schema and initialisation script appropriate for the database being // initialized. zMasterName is the name of the master table. string masterSchema = (E.OMIT_TEMPDB == 0 && db == 1 ? temp_master_schema : master_schema); string masterName = E.SCHEMA_TABLE(db); // Construct the schema tables. string[] args = new string[4]; args[0] = masterName; args[1] = "1"; args[2] = masterSchema; args[3] = null; InitData initData = new InitData(); initData.Ctx = ctx; initData.Db = db; initData.RC = RC.OK; initData.ErrMsg = errMsg; InitCallback(initData, 3, args, null); if (initData.RC != 0) { rc = initData.RC; goto error_out; } Table table = Parse.FindTable(ctx, masterName, ctx.DBs[db].Name); if (C._ALWAYS(table != null)) { table.TabFlags |= TF.Readonly; } // Create a cursor to hold the database open Context.DB dbAsObj = ctx.DBs[db]; if (dbAsObj.Bt == null) { if (E.OMIT_TEMPDB == 0 && C._ALWAYS(db == 1)) { E.DbSetProperty(ctx, 1, SCHEMA.SchemaLoaded); } return(RC.OK); } // If there is not already a read-only (or read-write) transaction opened on the b-tree database, open one now. If a transaction is opened, it // will be closed before this function returns. bool openedTransaction = false; dbAsObj.Bt.Enter(); if (!dbAsObj.Bt.IsInReadTrans()) { rc = dbAsObj.Bt.BeginTrans(0); if (rc != RC.OK) { C._setstring(ref errMsg, ctx, "%s", Main.ErrStr(rc)); goto initone_error_out; } openedTransaction = true; } // Get the database meta information. // Meta values are as follows: // meta[0] Schema cookie. Changes with each schema change. // meta[1] File format of schema layer. // meta[2] Size of the page cache. // meta[3] Largest rootpage (auto/incr_vacuum mode) // meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE // meta[5] User version // meta[6] Incremental vacuum mode // meta[7] unused // meta[8] unused // meta[9] unused // Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to the possible values of meta[4]. uint[] meta = new uint[5]; for (i = 0; i < meta.Length; i++) { dbAsObj.Bt.GetMeta((Btree.META)i + 1, ref meta[i]); } dbAsObj.Schema.SchemaCookie = (int)meta[(int)Btree.META.SCHEMA_VERSION - 1]; // If opening a non-empty database, check the text encoding. For the main database, set sqlite3.enc to the encoding of the main database. // For an attached ctx, it is an error if the encoding is not the same as sqlite3.enc. if (meta[(int)Btree.META.TEXT_ENCODING - 1] != 0) // text encoding { if (db == 0) { #if !OMIT_UTF16 // If opening the main database, set ENC(db). TEXTENCODE encoding = (TEXTENCODE)(meta[(int)Btree.META.TEXT_ENCODING - 1] & 3); if (encoding == 0) { encoding = TEXTENCODE.UTF8; } E.CTXENCODE(ctx, encoding); #else E.CTXENCODE(ctx, TEXTENCODE_UTF8); #endif } else { // If opening an attached database, the encoding much match ENC(db) if ((TEXTENCODE)meta[(int)Btree.META.TEXT_ENCODING - 1] != E.CTXENCODE(ctx)) { C._setstring(ref errMsg, ctx, "attached databases must use the same text encoding as main database"); rc = RC.ERROR; goto initone_error_out; } } } else { E.DbSetProperty(ctx, db, SCHEMA.Empty); } dbAsObj.Schema.Encode = E.CTXENCODE(ctx); if (dbAsObj.Schema.CacheSize == 0) { dbAsObj.Schema.CacheSize = DEFAULT_CACHE_SIZE; dbAsObj.Bt.SetCacheSize(dbAsObj.Schema.CacheSize); } // file_format==1 Version 3.0.0. // file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN // file_format==3 Version 3.1.4. // ditto but with non-NULL defaults // file_format==4 Version 3.3.0. // DESC indices. Boolean constants dbAsObj.Schema.FileFormat = (byte)meta[(int)Btree.META.FILE_FORMAT - 1]; if (dbAsObj.Schema.FileFormat == 0) { dbAsObj.Schema.FileFormat = 1; } if (dbAsObj.Schema.FileFormat > MAX_FILE_FORMAT) { C._setstring(ref errMsg, ctx, "unsupported file format"); rc = RC.ERROR; goto initone_error_out; } // Ticket #2804: When we open a database in the newer file format, clear the legacy_file_format pragma flag so that a VACUUM will // not downgrade the database and thus invalidate any descending indices that the user might have created. if (db == 0 && meta[(int)Btree.META.FILE_FORMAT - 1] >= 4) { ctx.Flags &= ~Context.FLAG.LegacyFileFmt; } // Read the schema information out of the schema tables Debug.Assert(ctx.Init.Busy); { string sql = C._mtagprintf(ctx, "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid", ctx.DBs[db].Name, masterName); #if !OMIT_AUTHORIZATION { Func <object, int, string, string, string, string, ARC> auth = ctx.Auth; ctx.Auth = null; #endif rc = sqlite3_exec(ctx, sql, InitCallback, initData, 0); //: errMsg = initData.ErrMsg; #if !OMIT_AUTHORIZATION ctx.Auth = auth; } #endif if (rc == RC.OK) { rc = initData.RC; } C._tagfree(ctx, ref sql); #if !OMIT_ANALYZE if (rc == RC.OK) { sqlite3AnalysisLoad(ctx, db); } #endif } if (ctx.MallocFailed) { rc = RC.NOMEM; Main.ResetAllSchemasOfConnection(ctx); } if (rc == RC.OK || (ctx.Flags & Context.FLAG.RecoveryMode) != 0) { // Black magic: If the SQLITE_RecoveryMode flag is set, then consider the schema loaded, even if errors occurred. In this situation the // current sqlite3_prepare() operation will fail, but the following one will attempt to compile the supplied statement against whatever subset // of the schema was loaded before the error occurred. The primary purpose of this is to allow access to the sqlite_master table // even when its contents have been corrupted. E.DbSetProperty(ctx, db, DB.SchemaLoaded); rc = RC.OK; } // Jump here for an error that occurs after successfully allocating curMain and calling sqlite3BtreeEnter(). For an error that occurs // before that point, jump to error_out. initone_error_out: if (openedTransaction) { dbAsObj.Bt.Commit(); } dbAsObj.Bt.Leave(); error_out: if (rc == RC.NOMEM || rc == RC.IOERR_NOMEM) { ctx.MallocFailed = true; } return(rc); }
public static RC MemSetStr(Mem mem, string z, int offset, int n, TEXTENCODE encode, Action <object> del) { Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((mem.Flags & MEM.RowSet) == 0); // If z is a NULL pointer, set pMem to contain an SQL NULL. if (z == null || z.Length < offset) { MemSetNull(mem); return(RC.OK); } int limit = (mem.Ctx != null ? mem.Ctx.Limits[(int)LIMIT.LENGTH] : CORE_MAX_LENGTH); // Maximum allowed string or blob size MEM flags = (encode == 0 ? MEM.Blob : MEM.Str); // New value for pMem->flags int bytes = n; // New value for pMem->n if (bytes < 0) { Debug.Assert(encode != 0); if (encode == TEXTENCODE.UTF8) { for (bytes = 0; bytes <= limit && bytes < z.Length - offset && z[offset + bytes] != 0; bytes++) { } } else { for (bytes = 0; bytes <= limit && z[bytes + offset] != 0 || z[offset + bytes + 1] != 0; bytes += 2) { } } flags |= MEM.Term; } // The following block sets the new values of Mem.z and Mem.xDel. It also sets a flag in local variable "flags" to indicate the memory // management (one of MEM_Dyn or MEM_Static). if (del == C.DESTRUCTOR_TRANSIENT) { int allocs = bytes; if ((flags & MEM.Term) != 0) { allocs += (encode == TEXTENCODE.UTF8 ? 1 : 2); } if (bytes > limit) { return(RC.TOOBIG); } if (MemGrow(mem, (int)allocs, false) != 0) { return(RC.NOMEM); } //if (allocs < z.Length) mem.Z = new byte[allocs]; Buffer.BlockCopy(z, 0, mem.Z, 0, allocs); } //else if (encode == 0) { mem.Z = null; mem.Z_ = C._alloc(n); for (int i = 0; i < n && i < z.Length - offset; i++) { mem.Z_[i] = (byte)z[offset + i]; } } else { mem.Z = (n > 0 && z.Length - offset > n ? z.Substring(offset, n) : z.Substring(offset)); C._free(ref mem.Z_); } } else if (del == C.DESTRUCTOR_DYNAMIC) { MemRelease(mem); //: mem->Malloc = mem->Z = (char *)z; if (encode == 0) { mem.Z = null; if (mem.Z_ != null) { C._free(ref mem.Z_); } mem.Z_ = Encoding.UTF8.GetBytes(offset == 0 ? z : z.Length + offset < n ? z.Substring(offset, n) : z.Substring(offset)); } else { mem.Z = (n > 0 && z.Length - offset > n ? z.Substring(offset, n) : z.Substring(offset)); mem.Z_ = null; } mem.Del = null; } else { MemRelease(mem); if (encode == 0) //: mem->Z = (char *)z; { mem.Z = null; if (mem.Z_ != null) { C._free(ref mem.Z_); } mem.Z_ = Encoding.UTF8.GetBytes(offset == 0 ? z : z.Length + offset < n ? z.Substring(offset, n) : z.Substring(offset)); } else { mem.Z = (n > 0 && z.Length - offset > n ? z.Substring(offset, n) : z.Substring(offset)); C._free(ref mem.Z_); } mem.Del = del; flags |= (del == C.DESTRUCTOR_STATIC ? MEM.Static : MEM.Dyn); } mem.N = bytes; mem.Flags = MEM.Blob | MEM.Term; mem.Encode = (encode == 0 ? TEXTENCODE.UTF8 : encode); mem.Type = (encode == 0 ? TYPE.BLOB : TYPE.TEXT); #if !OMIT_UTF16 if (mem.Encode != TEXTENCODE.UTF8 && MemHandleBom(mem) != 0) { return(RC.NOMEM); } #endif return(bytes > limit ? RC.TOOBIG : RC.OK); }
public static bool Atof(string z, ref double out_, int length, TEXTENCODE encode) { #if !OMIT_FLOATING_POINT out_ = 0.0; // Default return value, in case of an error if (string.IsNullOrEmpty(z)) { return(false); } // getsize int zIdx = 0; int incr = (encode == TEXTENCODE.UTF8 ? 1 : 2); if (encode == TEXTENCODE.UTF16BE) { zIdx++; } // skip leading spaces while (zIdx < length && char.IsWhiteSpace(z[zIdx])) { zIdx++; } if (zIdx >= length) { return(false); } // get sign of significand int sign = 1; // sign of significand if (z[zIdx] == '-') { sign = -1; zIdx += incr; } else if (z[zIdx] == '+') { zIdx += incr; } // sign * significand * (10 ^ (esign * exponent)) long s = 0; // significand int d = 0; // adjust exponent for shifting decimal point int esign = 1; // sign of exponent int e = 0; // exponent bool nonNum = true; // True exponent is either not used or is well-formed int digits = 0; // skip leading zeroes while (zIdx < z.Length && z[zIdx] == '0') { zIdx += incr; digits++; } // copy max significant digits to significand while (zIdx < length && char.IsDigit(z[zIdx]) && s < ((long.MaxValue - 9) / 10)) { s = s * 10 + (z[zIdx] - '0'); zIdx += incr; digits++; } while (zIdx < length && char.IsDigit(z[zIdx])) { zIdx += incr; digits++; d++; } if (zIdx >= length) { goto do_atof_calc; } // if decimal point is present if (z[zIdx] == '.') { zIdx += incr; // copy digits from after decimal to significand (decrease exponent by d to shift decimal right) while (zIdx < length && char.IsDigit(z[zIdx]) && s < ((long.MaxValue - 9) / 10)) { s = s * 10 + (z[zIdx] - '0'); zIdx += incr; digits++; d--; } while (zIdx < length && char.IsDigit(z[zIdx])) { zIdx += incr; digits++; } // skip non-significant digits } if (zIdx >= length) { goto do_atof_calc; } // if exponent is present if (z[zIdx] == 'e' || z[zIdx] == 'E') { zIdx += incr; nonNum = false; if (zIdx >= length) { goto do_atof_calc; } // get sign of exponent if (z[zIdx] == '-') { esign = -1; zIdx += incr; } else if (z[zIdx] == '+') { zIdx += incr; } // copy digits to exponent while (zIdx < length && char.IsDigit(z[zIdx])) { e = e * 10 + (z[zIdx] - '0'); zIdx += incr; nonNum = true; } } // skip trailing spaces if (digits != 0 && nonNum) { while (zIdx < length && char.IsWhiteSpace(z[zIdx])) { zIdx += incr; } } do_atof_calc: // adjust exponent by d, and update sign e = (e * esign) + d; if (e < 0) { esign = -1; e *= -1; } else { esign = 1; } // if !significand double result = 0.0; if (s == 0) { result = (sign < 0 && digits != 0 ? -0.0 : 0.0); // In the IEEE 754 standard, zero is signed. Add the sign if we've seen at least one digit } else { // attempt to reduce exponent if (esign > 0) { while (s < (long.MaxValue / 10) && e > 0) { e--; s *= 10; } } else { while ((s % 10) == 0 && e > 0) { e--; s /= 10; } } // adjust the sign of significand s = (sign < 0 ? -s : s); // if exponent, scale significand as appropriate and store in result. if (e != 0) { double scale = 1.0; // attempt to handle extremely small/large numbers better if (e > 307 && e < 342) { while ((e % 308) != 0) { scale *= 1.0e+1; e -= 1; } if (esign < 0) { result = s / scale; result /= 1.0e+308; } else { result = s * scale; result *= 1.0e+308; } } else if (e >= 342) { result = (esign < 0 ? 0.0 * s : 1e308 * 1e308 * s); // Infinity } else { // 1.0e+22 is the largest power of 10 than can be represented exactly. while ((e % 22) != 0) { scale *= 1.0e+1; e -= 1; } while (e > 0) { scale *= 1.0e+22; e -= 22; } result = (esign < 0 ? s / scale : s * scale); } } else { result = (double)s; } } out_ = result; // store the result return(zIdx >= length && digits > 0 && nonNum); // return true if number and no extra non-whitespace chracters after #else return(!Atoi64(z, out_, length, encode)); #endif }
public static RC MemTranslate(Mem mem, TEXTENCODE desiredEncode) { Debugger.Break(); // TODO - int len; // Maximum length of output string in bytes //unsigned char *zOut; // Output buffer //unsigned char *zIn; // Input iterator //unsigned char *zTerm; // End of input //unsigned char *z; // Output iterator //unsigned int c; Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((mem.Flags & MEM.Str) != 0); Debug.Assert(mem.Encode != desiredEncode); Debug.Assert(mem.Encode != 0); Debug.Assert(mem.N >= 0); #if TRANSLATE_TRACE && DEBUG //{ // char[] buf = new char[100]; // MemPrettyPrint(mem, zBuf); // fprintf(stderr, "INPUT: %s\n", zBuf); //} #endif Debugger.Break(); // If the translation is between UTF-16 little and big endian, then all that is required is to swap the byte order. This case is handled differently from the others. //if (mem.Encode != TEXTENCODE.UTF8 && desiredEncode != TEXTENCODE.UTF8) //{ // u8 temp; // RC rc = MemMakeWriteable(mem); // if (rc != RC.OK) // { // Debug.Assert(rc == RC.NOMEM); // return RC.NOMEM; // } // in_ = mem.Z; // term_ = in_[mem.N & ~1]; // while (in_ < term_) // { // temp = in_; // in_ = (in_ + 1); // in_++; // in_++ = temp; // } // mem.Encode = desiredEncode; // goto translate_out; //} // Set len to the maximum number of bytes required in the output buffer. if (desiredEncode == TEXTENCODE.UTF8) { // When converting from UTF-16, the maximum growth results from translating a 2-byte character to a 4-byte UTF-8 character. // A single byte is required for the output string nul-terminator. mem.N &= ~1; len = mem.N * 2 + 1; } else { // When converting from UTF-8 to UTF-16 the maximum growth is caused when a 1-byte UTF-8 character is translated into a 2-byte UTF-16 // character. Two bytes are required in the output buffer for the nul-terminator. len = mem.N * 2 + 2; } Debugger.Break(); // Set zIn to point at the start of the input buffer and zTerm to point 1 byte past the end. // Variable zOut is set to point at the output buffer, space obtained from sqlite3_malloc(). //zIn = (u8*)pMem.z; //zTerm = &zIn[pMem->n]; //zOut = sqlite3DbMallocRaw(pMem->db, len); //if( !zOut ){ // return SQLITE_NOMEM; //} //z = zOut; //if( pMem->enc==SQLITE_UTF8 ){ // if( desiredEnc==SQLITE_UTF16LE ){ // /* UTF-8 -> UTF-16 Little-endian */ // while( zIn<zTerm ){ ///* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */ //READ_UTF8(zIn, zTerm, c); // WRITE_UTF16LE(z, c); // } // }else{ // Debug.Assert( desiredEnc==SQLITE_UTF16BE ); // /* UTF-8 -> UTF-16 Big-endian */ // while( zIn<zTerm ){ ///* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */ //READ_UTF8(zIn, zTerm, c); // WRITE_UTF16BE(z, c); // } // } // pMem->n = (int)(z - zOut); // *z++ = 0; //}else{ // Debug.Assert( desiredEnc==SQLITE_UTF8 ); // if( pMem->enc==SQLITE_UTF16LE ){ // /* UTF-16 Little-endian -> UTF-8 */ // while( zIn<zTerm ){ // READ_UTF16LE(zIn, zIn<zTerm, c); // WRITE_UTF8(z, c); // } // }else{ // /* UTF-16 Big-endian -> UTF-8 */ // while( zIn<zTerm ){ // READ_UTF16BE(zIn, zIn<zTerm, c); // WRITE_UTF8(z, c); // } // } // pMem->n = (int)(z - zOut); //} //*z = 0; //Debug.Assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); //sqlite3VdbeMemRelease(pMem); //pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem); //pMem->enc = desiredEnc; //pMem->flags |= (MEM_Term|MEM_Dyn); //pMem.z = (char*)zOut; //pMem.zMalloc = pMem.z; //translate_out: #if TRANSLATE_TRACE && DEBUG //{ // char[] zBuf = new char[100]; // MemPrettyPrint(mem, zBuf); // fprintf(stderr, "OUTPUT: %s\n", zBuf); //} #endif return RC.OK; }
public string Utf8to16(Context ctx, TEXTENCODE encode, string z, int n, ref int out_) { Mem m = new Mem(); m.Ctx = ctx; MemSetStr(m, z, n, TEXTENCODE.UTF8, C.DESTRUCTOR_STATIC); if (MemTranslate(m, encode) != RC.OK) { Debug.Assert(ctx.MallocFailed); return null; } //Debug.Assert(m.Z == m.zMalloc); out_ = m.N; return m.Z; }
public static RC ValueFromExpr(Context ctx, Expr expr, TEXTENCODE encode, AFF affinity, ref Mem value) { if (expr == null) { value = null; return(RC.OK); } TK op = expr.OP; // op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT3. The ifdef here is to enable us to achieve 100% branch test coverage even when SQLITE_ENABLE_STAT3 is omitted. #if ENABLE_STAT3 if (op == TK.REGISTER) { op = expr.OP2; } #else if (C._NEVER(op == TK.REGISTER)) { op = expr.OP2; } #endif // Handle negative integers in a single step. This is needed in the case when the value is -9223372036854775808. int negInt = 1; string neg = string.Empty; if (op == TK.UMINUS && (expr.Left.OP == TK.INTEGER || expr.Left.OP == TK.FLOAT)) { expr = expr.Left; op = expr.OP; negInt = -1; neg = "-"; } Mem mem = null; string memAsString = null; if (op == TK.STRING || op == TK.FLOAT || op == TK.INTEGER) { mem = ValueNew(ctx); if (mem == null) { goto no_mem; } if (E.ExprHasProperty(expr, EP.IntValue)) { MemSetInt64(mem, (long)expr.u.I * negInt); } else { memAsString = C._mtagprintf(ctx, "%s%s", neg, expr.u.Token); if (memAsString == null) { goto no_mem; } ValueSetStr(mem, -1, memAsString, TEXTENCODE.UTF8, C.DESTRUCTOR_DYNAMIC); if (op == TK.FLOAT) { mem.Type = TYPE.FLOAT; } } if ((op == TK.INTEGER || op == TK.FLOAT) && affinity == AFF.NONE) { ValueApplyAffinity(mem, AFF.NUMERIC, TEXTENCODE.UTF8); } else { ValueApplyAffinity(mem, affinity, TEXTENCODE.UTF8); } if ((mem.Flags & (MEM.Int | MEM.Real)) != 0) { mem.Flags &= ~MEM.Str; } if (encode != TEXTENCODE.UTF8) { ChangeEncoding(mem, encode); } } else if (op == TK.UMINUS) { // This branch happens for multiple negative signs. Ex: -(-5) if (ValueFromExpr(ctx, expr.Left, encode, affinity, ref mem) == RC.OK) { MemNumerify(mem); if (mem.u.I == long.MinValue) { mem.Flags &= MEM.Int; mem.Flags |= MEM.Real; mem.R = (double)int.MaxValue; } else { mem.u.I = -mem.u.I; } mem.R = -mem.R; ValueApplyAffinity(mem, affinity, encode); } } else if (op == TK.NULL) { mem = ValueNew(ctx); if (mem == null) { goto no_mem; } } #if !OMIT_BLOB_LITERAL else if (op == TK.BLOB) { Debug.Assert(expr.u.Token[0] == 'x' || expr.u.Token[0] == 'X'); Debug.Assert(expr.u.Token[1] == '\''); mem = ValueNew(ctx); if (mem == null) { goto no_mem; } memAsString = expr.u.Token.Substring(2); int memAsStringLength = memAsString.Length - 1; Debug.Assert(memAsString[memAsStringLength] == '\''); byte[] blob = C._taghextoblob(ctx, memAsString, memAsStringLength); MemSetStr(mem, Encoding.UTF8.GetString(blob, 0, blob.Length), memAsStringLength / 2, 0, C.DESTRUCTOR_DYNAMIC); } #endif if (mem != null) { MemStoreType(mem); } value = mem; return(RC.OK); no_mem: ctx.MallocFailed = true; C._tagfree(ctx, ref memAsString); ValueFree(ref mem); value = null; return(RC.NOMEM); }
public static RC MemStringify(Mem mem, TEXTENCODE encode) { MEM f = mem.Flags; Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((f & MEM.Zero) == 0); Debug.Assert((f & (MEM.Str | MEM.Blob)) == 0); Debug.Assert((f & (MEM.Int | MEM.Real)) != 0); Debug.Assert((mem.Flags & MEM.RowSet) == 0); //: Debug.Assert(C._HASALIGNMENT8(mem)); const int bytes = 32; if (MemGrow(mem, bytes, false) != 0) return RC.NOMEM; // For a Real or Integer, use sqlite3_mprintf() to produce the UTF-8 string representation of the value. Then, if the required encoding // is UTF-16le or UTF-16be do a translation. // FIX ME: It would be better if sqlite3_snprintf() could do UTF-16. if ((f & MEM.Int) != 0) mem.Z = mem.u.I.ToString(); //: __snprintf(mem->Z, bytes, "%lld", mem->u.I); else { Debug.Assert((f & MEM.Real) != 0); if (double.IsNegativeInfinity(mem.R)) mem.Z = "-Inf"; else if (double.IsInfinity(mem.R)) mem.Z = "Inf"; else if (double.IsPositiveInfinity(mem.R)) mem.Z = "+Inf"; else if (mem.R.ToString(CultureInfo.InvariantCulture).Contains(".")) mem.Z = mem.R.ToString(CultureInfo.InvariantCulture).ToLower(); //: __snprintf(mem->Z, bytes, "%!.15g", mem->R); else mem.Z = mem.R.ToString(CultureInfo.InvariantCulture) + ".0"; } mem.N = mem.Z.Length; mem.Encode = TEXTENCODE.UTF8; mem.Flags |= MEM.Str | MEM.Term; ChangeEncoding(mem, encode); return RC.OK; }
public static RC MemTranslate(Mem mem, TEXTENCODE desiredEncode) { Debugger.Break(); // TODO - int len; // Maximum length of output string in bytes //unsigned char *zOut; // Output buffer //unsigned char *zIn; // Input iterator //unsigned char *zTerm; // End of input //unsigned char *z; // Output iterator //unsigned int c; Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((mem.Flags & MEM.Str) != 0); Debug.Assert(mem.Encode != desiredEncode); Debug.Assert(mem.Encode != 0); Debug.Assert(mem.N >= 0); #if TRANSLATE_TRACE && DEBUG //{ // char[] buf = new char[100]; // MemPrettyPrint(mem, zBuf); // fprintf(stderr, "INPUT: %s\n", zBuf); //} #endif Debugger.Break(); // If the translation is between UTF-16 little and big endian, then all that is required is to swap the byte order. This case is handled differently from the others. //if (mem.Encode != TEXTENCODE.UTF8 && desiredEncode != TEXTENCODE.UTF8) //{ // u8 temp; // RC rc = MemMakeWriteable(mem); // if (rc != RC.OK) // { // Debug.Assert(rc == RC.NOMEM); // return RC.NOMEM; // } // in_ = mem.Z; // term_ = in_[mem.N & ~1]; // while (in_ < term_) // { // temp = in_; // in_ = (in_ + 1); // in_++; // in_++ = temp; // } // mem.Encode = desiredEncode; // goto translate_out; //} // Set len to the maximum number of bytes required in the output buffer. if (desiredEncode == TEXTENCODE.UTF8) { // When converting from UTF-16, the maximum growth results from translating a 2-byte character to a 4-byte UTF-8 character. // A single byte is required for the output string nul-terminator. mem.N &= ~1; len = mem.N * 2 + 1; } else { // When converting from UTF-8 to UTF-16 the maximum growth is caused when a 1-byte UTF-8 character is translated into a 2-byte UTF-16 // character. Two bytes are required in the output buffer for the nul-terminator. len = mem.N * 2 + 2; } Debugger.Break(); // Set zIn to point at the start of the input buffer and zTerm to point 1 byte past the end. // Variable zOut is set to point at the output buffer, space obtained from sqlite3_malloc(). //zIn = (u8*)pMem.z; //zTerm = &zIn[pMem->n]; //zOut = sqlite3DbMallocRaw(pMem->db, len); //if( !zOut ){ // return SQLITE_NOMEM; //} //z = zOut; //if( pMem->enc==SQLITE_UTF8 ){ // if( desiredEnc==SQLITE_UTF16LE ){ // /* UTF-8 -> UTF-16 Little-endian */ // while ( zIn<zTerm ){ ///* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */ //READ_UTF8(zIn, zTerm, c); // WRITE_UTF16LE(z, c); // } // }else{ // Debug.Assert( desiredEnc==SQLITE_UTF16BE ); // /* UTF-8 -> UTF-16 Big-endian */ // while ( zIn<zTerm ){ ///* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */ //READ_UTF8(zIn, zTerm, c); // WRITE_UTF16BE(z, c); // } // } // pMem->n = (int)(z - zOut); // *z++ = 0; //}else{ // Debug.Assert( desiredEnc==SQLITE_UTF8 ); // if( pMem->enc==SQLITE_UTF16LE ){ // /* UTF-16 Little-endian -> UTF-8 */ // while ( zIn<zTerm ){ // READ_UTF16LE(zIn, zIn<zTerm, c); // WRITE_UTF8(z, c); // } // }else{ // /* UTF-16 Big-endian -> UTF-8 */ // while ( zIn<zTerm ){ // READ_UTF16BE(zIn, zIn<zTerm, c); // WRITE_UTF8(z, c); // } // } // pMem->n = (int)(z - zOut); //} //*z = 0; //Debug.Assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len ); //sqlite3VdbeMemRelease(pMem); //pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem); //pMem->enc = desiredEnc; //pMem->flags |= (MEM_Term|MEM_Dyn); //pMem.z = (char*)zOut; //pMem.zMalloc = pMem.z; //translate_out: #if TRANSLATE_TRACE && DEBUG //{ // char[] zBuf = new char[100]; // MemPrettyPrint(mem, zBuf); // fprintf(stderr, "OUTPUT: %s\n", zBuf); //} #endif return(RC.OK); }
public static RC MemSetStr(Mem mem, byte[] z, int offset, int n, TEXTENCODE encode, Action<object> del) { Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((mem.Flags & MEM.RowSet) == 0); // If z is a NULL pointer, set pMem to contain an SQL NULL. if (z == null || z.Length < offset) { MemSetNull(mem); return RC.OK; } int limit = (mem.Ctx != null ? mem.Ctx.Limits[(int)LIMIT.LENGTH] : CORE_MAX_LENGTH); // Maximum allowed string or blob size MEM flags = (encode == 0 ? MEM.Blob : MEM.Str); // New value for pMem->flags int bytes = n; // New value for pMem->n if (bytes < 0) { Debug.Assert(encode != 0); if (encode == TEXTENCODE.UTF8) for (bytes = 0; bytes <= limit && bytes < z.Length - offset && z[offset + bytes] != 0; bytes++) { } else for (bytes = 0; bytes <= limit && z[bytes + offset] != 0 || z[offset + bytes + 1] != 0; bytes += 2) { } } // The following block sets the new values of Mem.z and Mem.xDel. It also sets a flag in local variable "flags" to indicate the memory // management (one of MEM_Dyn or MEM_Static). Debug.Assert(encode == 0); { mem.Z = null; mem.Z_ = C._alloc(n); Buffer.BlockCopy(z, offset, mem.Z_, 0, n); } mem.N = bytes; mem.Flags = MEM.Blob | MEM.Term; mem.Encode = (encode == 0 ? TEXTENCODE.UTF8 : encode); mem.Type = (encode == 0 ? TYPE.BLOB : TYPE.TEXT); #if !OMIT_UTF16 if (mem.Encode != TEXTENCODE.UTF8 && MemHandleBom(mem) != 0) return RC.NOMEM; #endif return (bytes > limit ? RC.TOOBIG : RC.OK); }
public static int Atoi64(string z, out long out_, int length, TEXTENCODE encode) { if (z == null) { out_ = 0; return 1; } // get size int zIdx = 0;// string zStart; int incr = (encode == TEXTENCODE.UTF8 ? 1 : 2); if (encode == TEXTENCODE.UTF16BE) zIdx++; // skip leading spaces while (zIdx < length && char.IsWhiteSpace(z[zIdx])) zIdx += incr; // get sign of significand int neg = 0; // assume positive if (zIdx < length) { if (z[zIdx] == '-') { neg = 1; zIdx += incr; } else if (z[zIdx] == '+') zIdx += incr; } if (length > z.Length) length = z.Length; // skip leading zeros while (zIdx < length - 1 && z[zIdx] == '0') zIdx += incr; // Skip leading zeros. ulong u = 0; int c = 0; int i; for (i = zIdx; i < length && (c = z[i]) >= '0' && c <= '9'; i += incr) u = u * 10 + (ulong)(c - '0'); if (u > long.MaxValue) out_ = long.MinValue; else out_ = (neg != 0 ? -(long)u : (long)u); C.ASSERTCOVERAGE(i - zIdx == 18); C.ASSERTCOVERAGE(i - zIdx == 19); C.ASSERTCOVERAGE(i - zIdx == 20); if ((c != 0 && i < length) || i == zIdx || i - zIdx > 19 * incr) return 1; // zNum is empty or contains non-numeric text or is longer than 19 digits (thus guaranteeing that it is too large) else if (i - zIdx < 19 * incr) { Debug.Assert(u <= long.MaxValue); return 0; } // Less than 19 digits, so we know that it fits in 64 bits else { c = Compare2pow63(z.Substring(zIdx), incr); // zNum is a 19-digit numbers. Compare it against 9223372036854775808. if (c < 0) { Debug.Assert(u <= long.MaxValue); return 0; } // zNum is less than 9223372036854775808 so it fits else if (c > 0) return 1; // zNum is greater than 9223372036854775808 so it overflows else { Debug.Assert(u - 1 == long.MaxValue); Debug.Assert(out_ == long.MinValue); return neg != 0 ? 0 : 2; } // zNum is exactly 9223372036854775808. Fits if negative. The special case 2 overflow if positive } }
public static RC MemSetStr(Mem mem, string z, int offset, int n, TEXTENCODE encode, Action<object> del) { Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex)); Debug.Assert((mem.Flags & MEM.RowSet) == 0); // If z is a NULL pointer, set pMem to contain an SQL NULL. if (z == null || z.Length < offset) { MemSetNull(mem); return RC.OK; } int limit = (mem.Ctx != null ? mem.Ctx.Limits[(int)LIMIT.LENGTH] : CORE_MAX_LENGTH); // Maximum allowed string or blob size MEM flags = (encode == 0 ? MEM.Blob : MEM.Str); // New value for pMem->flags int bytes = n; // New value for pMem->n if (bytes < 0) { Debug.Assert(encode != 0); if (encode == TEXTENCODE.UTF8) for (bytes = 0; bytes <= limit && bytes < z.Length - offset && z[offset + bytes] != 0; bytes++) { } else for (bytes = 0; bytes <= limit && z[bytes + offset] != 0 || z[offset + bytes + 1] != 0; bytes += 2) { } flags |= MEM.Term; } // The following block sets the new values of Mem.z and Mem.xDel. It also sets a flag in local variable "flags" to indicate the memory // management (one of MEM_Dyn or MEM_Static). if (del == C.DESTRUCTOR_TRANSIENT) { int allocs = bytes; if ((flags & MEM.Term) != 0) allocs += (encode == TEXTENCODE.UTF8 ? 1 : 2); if (bytes > limit) return RC.TOOBIG; if (MemGrow(mem, (int)allocs, false) != 0) return RC.NOMEM; //if (allocs < z.Length) mem.Z = new byte[allocs]; Buffer.BlockCopy(z, 0, mem.Z, 0, allocs); } //else if (encode == 0) { mem.Z = null; mem.Z_ = C._alloc(n); for (int i = 0; i < n && i < z.Length - offset; i++) mem.Z_[i] = (byte)z[offset + i]; } else { mem.Z = (n > 0 && z.Length - offset > n ? z.Substring(offset, n) : z.Substring(offset)); C._free(ref mem.Z_); } } else if (del == C.DESTRUCTOR_DYNAMIC) { MemRelease(mem); //: mem->Malloc = mem->Z = (char *)z; if (encode == 0) { mem.Z = null; if (mem.Z_ != null) C._free(ref mem.Z_); mem.Z_ = Encoding.UTF8.GetBytes(offset == 0 ? z : z.Length + offset < n ? z.Substring(offset, n) : z.Substring(offset)); } else { mem.Z = (n > 0 && z.Length - offset > n ? z.Substring(offset, n) : z.Substring(offset)); mem.Z_ = null; } mem.Del = null; } else { MemRelease(mem); if (encode == 0) //: mem->Z = (char *)z; { mem.Z = null; if (mem.Z_ != null) C._free(ref mem.Z_); mem.Z_ = Encoding.UTF8.GetBytes(offset == 0 ? z : z.Length + offset < n ? z.Substring(offset, n) : z.Substring(offset)); } else { mem.Z = (n > 0 && z.Length - offset > n ? z.Substring(offset, n) : z.Substring(offset)); C._free(ref mem.Z_); } mem.Del = del; flags |= (del == C.DESTRUCTOR_STATIC ? MEM.Static : MEM.Dyn); } mem.N = bytes; mem.Flags = MEM.Blob | MEM.Term; mem.Encode = (encode == 0 ? TEXTENCODE.UTF8 : encode); mem.Type = (encode == 0 ? TYPE.BLOB : TYPE.TEXT); #if !OMIT_UTF16 if (mem.Encode != TEXTENCODE.UTF8 && MemHandleBom(mem) != 0) return RC.NOMEM; #endif return (bytes > limit ? RC.TOOBIG : RC.OK); }
static void ApplyAffinity(Mem rec, AFF affinity, TEXTENCODE encode) { if (affinity == AFF.TEXT) { // Only attempt the conversion to TEXT if there is an integer or real representation (blob and NULL do not get converted) but no string representation. if ((rec.Flags & MEM.Str) == 0 && (rec.Flags & (MEM.Real | MEM.Int)) != 0) MemStringify(rec, encode); //if ((rec.flags & (MEM.Blob | MEM.Str)) == (MEM.Blob | MEM.Str)) //{ // var sb = new StringBuilder(rec.zBLOB.Length); // for (int i = 0; i < rec.zBLOB.Length; i++) // sb.Append((char)rec.zBLOB[i]); // rec.Z = sb.ToString(); // C._free(ref rec.zBLOB); // rec.flags &= ~MEM_Blob; //} rec.Flags &= ~(MEM.Real | MEM.Int); } else if (affinity != AFF.NONE) { Debug.Assert(affinity == AFF.INTEGER || affinity == AFF.REAL || affinity == AFF.NUMERIC); ApplyNumericAffinity(rec); if ((rec.Flags & MEM.Real) != 0) IntegerAffinity(rec); } }
public static RC ValueFromExpr(Context ctx, Expr expr, TEXTENCODE encode, AFF affinity, ref Mem value) { if (expr == null) { value = null; return RC.OK; } TK op = expr.OP; // op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT3. The ifdef here is to enable us to achieve 100% branch test coverage even when SQLITE_ENABLE_STAT3 is omitted. #if ENABLE_STAT3 if (op == TK.REGISTER) op = expr.OP2; #else if (C._NEVER(op == TK.REGISTER)) op = expr.OP2; #endif // Handle negative integers in a single step. This is needed in the case when the value is -9223372036854775808. int negInt = 1; string neg = string.Empty; if (op == TK.UMINUS && (expr.Left.OP == TK.INTEGER || expr.Left.OP == TK.FLOAT)) { expr = expr.Left; op = expr.OP; negInt = -1; neg = "-"; } Mem mem = null; string memAsString = null; if (op == TK.STRING || op == TK.FLOAT || op == TK.INTEGER) { mem = ValueNew(ctx); if (mem == null) goto no_mem; if (E.ExprHasProperty(expr, EP.IntValue)) MemSetInt64(mem, (long)expr.u.I * negInt); else { memAsString = C._mtagprintf(ctx, "%s%s", neg, expr.u.Token); if (memAsString == null) goto no_mem; ValueSetStr(mem, -1, memAsString, TEXTENCODE.UTF8, C.DESTRUCTOR_DYNAMIC); if (op == TK.FLOAT) mem.Type = TYPE.FLOAT; } if ((op == TK.INTEGER || op == TK.FLOAT) && affinity == AFF.NONE) ValueApplyAffinity(mem, AFF.NUMERIC, TEXTENCODE.UTF8); else ValueApplyAffinity(mem, affinity, TEXTENCODE.UTF8); if ((mem.Flags & (MEM.Int | MEM.Real)) != 0) mem.Flags &= ~MEM.Str; if (encode != TEXTENCODE.UTF8) ChangeEncoding(mem, encode); } else if (op == TK.UMINUS) { // This branch happens for multiple negative signs. Ex: -(-5) if (ValueFromExpr(ctx, expr.Left, encode, affinity, ref mem) == RC.OK) { MemNumerify(mem); if (mem.u.I == long.MinValue) { mem.Flags &= MEM.Int; mem.Flags |= MEM.Real; mem.R = (double)int.MaxValue; } else mem.u.I = -mem.u.I; mem.R = -mem.R; ValueApplyAffinity(mem, affinity, encode); } } else if (op == TK.NULL) { mem = ValueNew(ctx); if (mem == null) goto no_mem; } #if !OMIT_BLOB_LITERAL else if (op == TK.BLOB) { Debug.Assert(expr.u.Token[0] == 'x' || expr.u.Token[0] == 'X'); Debug.Assert(expr.u.Token[1] == '\''); mem = ValueNew(ctx); if (mem == null) goto no_mem; memAsString = expr.u.Token.Substring(2); int memAsStringLength = memAsString.Length - 1; Debug.Assert(memAsString[memAsStringLength] == '\''); byte[] blob = C._taghextoblob(ctx, memAsString, memAsStringLength); MemSetStr(mem, Encoding.UTF8.GetString(blob, 0, blob.Length), memAsStringLength / 2, 0, C.DESTRUCTOR_DYNAMIC); } #endif if (mem != null) MemStoreType(mem); value = mem; return RC.OK; no_mem: ctx.MallocFailed = true; C._tagfree(ctx, ref memAsString); ValueFree(ref mem); value = null; return RC.NOMEM; }
public static RC MemSetStr(Mem mem, byte[] z, int n, TEXTENCODE encode, Action <object> del) { return(MemSetStr(mem, z, 0, (n >= 0 ? n : z.Length), encode, del)); }
static int ValueBytes(Mem mem, TEXTENCODE encode) { if ((mem.Flags & MEM.Blob) != 0 || ValueText(mem, encode) != null) return ((mem.Flags & MEM.Zero) != 0 ? mem.N + mem.u.Zeros : (mem.Z == null ? mem.Z_.Length : mem.N)); return 0; }
public string ExpandSql(string rawSql) { Context ctx = Ctx; // The database connection TextBuilder b = new TextBuilder(); // Accumulate the _output here TextBuilder.Init(b, 100, ctx.Limits[(int)LIMIT.LENGTH]); b.Tag = ctx; int rawSqlIdx = 0; int nextIndex = 1; // Index of next ? host parameter int idx = 0; // Index of a host parameter if (ctx.VdbeExecCnt > 1) { while (rawSqlIdx < rawSql.Length) { while (rawSql[rawSqlIdx++] != '\n' && rawSqlIdx < rawSql.Length) { ; } b.Append("-- ", 3); b.Append(rawSql, (int)rawSqlIdx); } } else { while (rawSqlIdx < rawSql.Length) { int tokenLength = 0; // Length of the parameter token int n = FindNextHostParameter(rawSql, rawSqlIdx, ref tokenLength); // Length of a token prefix Debug.Assert(n > 0); b.Append(rawSql.Substring(rawSqlIdx, n), n); rawSqlIdx += n; Debug.Assert(rawSqlIdx < rawSql.Length || tokenLength == 0); if (tokenLength == 0) { break; } if (rawSql[rawSqlIdx] == '?') { if (tokenLength > 1) { Debug.Assert(char.IsDigit(rawSql[rawSqlIdx + 1])); ConvertEx.Atoi(rawSql, rawSqlIdx + 1, ref idx); } else { idx = nextIndex; } } else { Debug.Assert(rawSql[rawSqlIdx] == ':' || rawSql[rawSqlIdx] == '$' || rawSql[rawSqlIdx] == '@'); C.ASSERTCOVERAGE(rawSql[rawSqlIdx] == ':'); C.ASSERTCOVERAGE(rawSql[rawSqlIdx] == '$'); C.ASSERTCOVERAGE(rawSql[rawSqlIdx] == '@'); idx = ParameterIndex(this, rawSql.Substring(rawSqlIdx, tokenLength), tokenLength); Debug.Assert(idx > 0); } rawSqlIdx += tokenLength; nextIndex = idx + 1; Debug.Assert(idx > 0 && idx <= Vars.length); Mem var = Vars[idx - 1]; // Value of a host parameter if ((var.Flags & MEM.Null) != 0) { b.Append("NULL", 4); } else if ((var.Flags & MEM.Int) != 0) { b.AppendFormat("%lld", var.u.I); } else if ((var.Flags & MEM.Real) != 0) { b.AppendFormat("%!.15g", var.R); } else if ((var.Flags & MEM.Str) != 0) { #if !OMIT_UTF16 TEXTENCODE encode = E.CTXENCODE(ctx); if (encode != TEXTENCODE.UTF8) { Mem utf8; //C._memset(&utf8, 0, sizeof(utf8)); utf8.Ctx = ctx; MemSetStr(utf8, var.Z, var.N, encode, C.DESTRUCTOR_STATIC); ChangeEncoding(utf8, TEXTENCODE.UTF8); b.AppendFormat("'%.*q'", utf8.N, utf8.Z); MemRelease(utf8); } else #endif b.AppendFormat("'%.*q'", var.N, var.Z); } else if ((var.Flags & MEM.Zero) != 0) { b.AppendFormat("zeroblob(%d)", var.u.Zeros); } else { Debug.Assert((var.Flags & MEM.Blob) != 0); b.Append("x'", 2); for (int i = 0; i < var.N; i++) { b.AppendFormat("%02x", var.u.Zeros[i] & 0xff); } b.Append("'", 1); } } } return(b.ToString()); }