Ejemplo n.º 1
0
        public static int MemCompare(Mem mem1, Mem mem2, CollSeq coll)
        {
            MEM f1 = mem1.Flags;
            MEM f2 = mem2.Flags;
            MEM cf = f1 | f2;
            Debug.Assert((cf & MEM.RowSet) == 0);

            // If one value is NULL, it is less than the other. If both values are NULL, return 0.
            if ((cf & MEM.Null) != 0)
                return (f2 & MEM.Null) - (f1 & MEM.Null);

            // If one value is a number and the other is not, the number is less. If both are numbers, compare as reals if one is a real, or as integers if both values are integers.
            if ((cf & (MEM.Int | MEM.Real)) != 0)
            {
                if ((f1 & (MEM.Int | MEM.Real)) == 0) return 1;
                if ((f2 & (MEM.Int | MEM.Real)) == 0) return -1;
                if ((f1 & f2 & MEM.Int) == 0)
                {
                    double r1 = ((f1 & MEM.Real) == 0 ? (double)mem1.u.I : mem1.R);
                    double r2 = ((f2 & MEM.Real) == 0 ? (double)mem2.u.I : mem2.R);
                    if (r1 < r2) return -1;
                    if (r1 > r2) return 1;
                    return 0;
                }
                Debug.Assert((f1 & MEM.Int) != 0);
                Debug.Assert((f2 & MEM.Int) != 0);
                if (mem1.u.I < mem2.u.I) return -1;
                if (mem1.u.I > mem2.u.I) return 1;
                return 0;
            }

            // If one value is a string and the other is a blob, the string is less. If both are strings, compare using the collating functions.
            int r;
            if ((cf & MEM.Str) != 0)
            {
                if ((f1 & MEM.Str) == 0) return 1;
                if ((f2 & MEM.Str) == 0) return -1;

                Debug.Assert(mem1.Encode == mem2.Encode);
                Debug.Assert(mem1.Encode == TEXTENCODE.UTF8 || mem1.Encode == TEXTENCODE.UTF16LE || mem1.Encode == TEXTENCODE.UTF16BE);
                // The collation sequence must be defined at this point, even if the user deletes the collation sequence after the vdbe program is
                // compiled (this was not always the case).
                Debug.Assert(coll == null || coll.Cmp != null);
                if (coll != null)
                {
                    if (mem1.Encode == coll.Encode)
                        return coll.Cmp(coll.User, mem1.N, mem1.Z, mem2.N, mem2.Z); // The strings are already in the correct encoding.  Call the comparison function directly
                    else
                    {
                        Mem c1 = C._alloc(c1); //: _memset(&c1, 0, sizeof(c1));
                        Mem c2 = C._alloc(c2); //: _memset(&c2, 0, sizeof(c2));
                        MemShallowCopy(c1, mem1, MEM.Ephem);
                        MemShallowCopy(c2, mem2, MEM.Ephem);
                        string v1 = ValueText(c1, coll.Encode);
                        int n1 = (v1 == null ? 0 : c1.N);
                        string v2 = ValueText(c2, coll.Encode);
                        int n2 = (v2 == null ? 0 : c2.N);
                        r = coll.Cmp(coll.User, n1, v1, n2, v2);
                        MemRelease(c1);
                        MemRelease(c2);
                        return r;
                    }
                }
                // If a NULL pointer was passed as the collate function, fall through to the blob case and use memcmp().
            }
            // Both values must be blobs.  Compare using memcmp().
            if ((mem1.Flags & MEM.Blob) != 0)
                if (mem1.Z_ != null) r = C._memcmp(mem1.Z_, mem2.Z_, (mem1.N > mem2.N ? mem2.N : mem1.N));
                else r = C._memcmp(mem1.Z, mem2.Z_, (mem1.N > mem2.N ? mem2.N : mem1.N));
            else r = C._memcmp(mem1.Z, mem2.Z, (mem1.N > mem2.N ? mem2.N : mem1.N));
            if (r == 0)
                r = mem1.N - mem2.N;
            return r;
        }
Ejemplo n.º 2
0
        public static int MemCompare(Mem mem1, Mem mem2, CollSeq coll)
        {
            MEM f1 = mem1.Flags;
            MEM f2 = mem2.Flags;
            MEM cf = f1 | f2;

            Debug.Assert((cf & MEM.RowSet) == 0);

            // If one value is NULL, it is less than the other. If both values are NULL, return 0.
            if ((cf & MEM.Null) != 0)
            {
                return((f2 & MEM.Null) - (f1 & MEM.Null));
            }

            // If one value is a number and the other is not, the number is less. If both are numbers, compare as reals if one is a real, or as integers if both values are integers.
            if ((cf & (MEM.Int | MEM.Real)) != 0)
            {
                if ((f1 & (MEM.Int | MEM.Real)) == 0)
                {
                    return(1);
                }
                if ((f2 & (MEM.Int | MEM.Real)) == 0)
                {
                    return(-1);
                }
                if ((f1 & f2 & MEM.Int) == 0)
                {
                    double r1 = ((f1 & MEM.Real) == 0 ? (double)mem1.u.I : mem1.R);
                    double r2 = ((f2 & MEM.Real) == 0 ? (double)mem2.u.I : mem2.R);
                    if (r1 < r2)
                    {
                        return(-1);
                    }
                    if (r1 > r2)
                    {
                        return(1);
                    }
                    return(0);
                }
                Debug.Assert((f1 & MEM.Int) != 0);
                Debug.Assert((f2 & MEM.Int) != 0);
                if (mem1.u.I < mem2.u.I)
                {
                    return(-1);
                }
                if (mem1.u.I > mem2.u.I)
                {
                    return(1);
                }
                return(0);
            }

            // If one value is a string and the other is a blob, the string is less. If both are strings, compare using the collating functions.
            int r;

            if ((cf & MEM.Str) != 0)
            {
                if ((f1 & MEM.Str) == 0)
                {
                    return(1);
                }
                if ((f2 & MEM.Str) == 0)
                {
                    return(-1);
                }

                Debug.Assert(mem1.Encode == mem2.Encode);
                Debug.Assert(mem1.Encode == TEXTENCODE.UTF8 || mem1.Encode == TEXTENCODE.UTF16LE || mem1.Encode == TEXTENCODE.UTF16BE);
                // The collation sequence must be defined at this point, even if the user deletes the collation sequence after the vdbe program is
                // compiled (this was not always the case).
                Debug.Assert(coll == null || coll.Cmp != null);
                if (coll != null)
                {
                    if (mem1.Encode == coll.Encode)
                    {
                        return(coll.Cmp(coll.User, mem1.N, mem1.Z, mem2.N, mem2.Z)); // The strings are already in the correct encoding.  Call the comparison function directly
                    }
                    else
                    {
                        Mem c1 = C._alloc(c1); //: _memset(&c1, 0, sizeof(c1));
                        Mem c2 = C._alloc(c2); //: _memset(&c2, 0, sizeof(c2));
                        MemShallowCopy(c1, mem1, MEM.Ephem);
                        MemShallowCopy(c2, mem2, MEM.Ephem);
                        string v1 = ValueText(c1, coll.Encode);
                        int    n1 = (v1 == null ? 0 : c1.N);
                        string v2 = ValueText(c2, coll.Encode);
                        int    n2 = (v2 == null ? 0 : c2.N);
                        r = coll.Cmp(coll.User, n1, v1, n2, v2);
                        MemRelease(c1);
                        MemRelease(c2);
                        return(r);
                    }
                }
                // If a NULL pointer was passed as the collate function, fall through to the blob case and use memcmp().
            }
            // Both values must be blobs.  Compare using memcmp().
            if ((mem1.Flags & MEM.Blob) != 0)
            {
                if (mem1.Z_ != null)
                {
                    r = C._memcmp(mem1.Z_, mem2.Z_, (mem1.N > mem2.N ? mem2.N : mem1.N));
                }
                else
                {
                    r = C._memcmp(mem1.Z, mem2.Z_, (mem1.N > mem2.N ? mem2.N : mem1.N));
                }
            }
            else
            {
                r = C._memcmp(mem1.Z, mem2.Z, (mem1.N > mem2.N ? mem2.N : mem1.N));
            }
            if (r == 0)
            {
                r = mem1.N - mem2.N;
            }
            return(r);
        }