示例#1
0
文件: Callback.cs 项目: BclEx/GpuEx
        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
        }
示例#2
0
 public static void ValueSetStr(Mem mem, int n, string z, TEXTENCODE encode, Action <object> del)
 {
     if (mem != null)
     {
         MemSetStr(mem, z, n, encode, del);
     }
 }
示例#3
0
        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);
        }
示例#4
0
文件: Callback.cs 项目: BclEx/GpuEx
        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);
        }
示例#5
0
        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);
        }
示例#6
0
        // 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);
            }
        }
示例#7
0
 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);
 }
示例#8
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);
        }
示例#9
0
        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);
        }
示例#10
0
        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);
        }
示例#11
0
文件: Callback.cs 项目: BclEx/GpuEx
 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);
 }
示例#12
0
        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);
        }
示例#13
0
文件: VdbeInt_h.cs 项目: BclEx/GpuEx
        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;
        }
示例#14
0
        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
        }
示例#15
0
文件: Callback.cs 项目: BclEx/GpuEx
        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);
        }
示例#16
0
 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);
 }
示例#17
0
        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
            }
        }
示例#18
0
        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
        }
示例#19
0
 public static void CTXENCODE(BContext ctx, TEXTENCODE encode)
 {
     ctx.DBs[0].Schema.Encode = encode;
 }
示例#20
0
文件: Vdbe.cs 项目: BclEx/GpuStructs
 static void ValueApplyAffinity(Mem mem, char affinity, TEXTENCODE encode)
 {
     ApplyAffinity(mem, (AFF)affinity, encode);
 }
示例#21
0
 static RC MemSetStr(Mem mem, string z, int n, TEXTENCODE encode, Action<object> del) { return MemSetStr(mem, z, 0, n, encode, del); }
示例#22
0
 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); }
示例#23
0
 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;
 }
示例#24
0
        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
            }
        }
示例#25
0
        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);
        }
示例#26
0
        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
        }
示例#27
0
 public static void ValueSetStr(Mem mem, int n, string z, TEXTENCODE encode, Action<object> del)
 {
     if (mem != null) MemSetStr(mem, z, n, encode, del);
 }
示例#28
0
 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);
 }
示例#29
0
 public static void CTXENCODE(BContext ctx, TEXTENCODE encode) { ctx.DBs[0].Schema.Encode = encode; }
示例#30
0
文件: Callback.cs 项目: BclEx/GpuEx
        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);
        }
示例#31
0
 static RC MemSetStr(Mem mem, string z, int n, TEXTENCODE encode, Action <object> del)
 {
     return(MemSetStr(mem, z, 0, n, encode, del));
 }
示例#32
0
        //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);
        }
示例#33
0
        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);
        }
示例#34
0
        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
        }
示例#35
0
        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;
        }
示例#36
0
 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;
 }
示例#37
0
        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);
        }
示例#38
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;
        }
示例#39
0
        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);
        }
示例#40
0
        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);
        }
示例#41
0
        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
            }
        }
示例#42
0
        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);
        }
示例#43
0
文件: Vdbe.cs 项目: BclEx/GpuStructs
 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);
     }
 }
示例#44
0
        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;
        }
示例#45
0
 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));
 }
示例#46
0
 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;
 }
示例#47
0
文件: Vdbe+Trace.cs 项目: BclEx/GpuEx
        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());
        }