예제 #1
0
파일: key.cpp 프로젝트: kzys/mongo
bool KeyV1::woEqual(const KeyV1& right) const {
    const unsigned char *l = _keyData;
    const unsigned char *r = right._keyData;

    if( (*l|*r) == IsBSON ) {
        return toBson().equal(right.toBson());
    }

    while( 1 ) {
        char lval = *l;
        char rval = *r;
        if( (lval&(cCANONTYPEMASK|cHASMORE)) != (rval&(cCANONTYPEMASK|cHASMORE)) )
            return false;
        l++;
        r++;
        switch( lval&cCANONTYPEMASK ) {
        case coid:
            if( *((unsigned*) l) != *((unsigned*) r) )
                return false;
            l += 4;
            r += 4;
        case cdate:
        case cdouble:
            if( *((unsigned long long *) l) != *((unsigned long long *) r) )
                return false;
            l += 8;
            r += 8;
            break;
        case cstring:
        {
            unsigned sz = ((unsigned) *l) + 1;
            if( memcmp(l, r, sz) ) // first byte checked is the length byte
                return false;
            l += sz;
            r += sz;
            break;
        }
        case cbindata:
        {
            int len = binDataCodeToLength(*l) + 1;
            if( memcmp(l, r, len) )
                return false;
            l += len;
            r += len;
            break;
        }
        case cminkey:
        case cnull:
        case cfalse:
        case ctrue:
        case cmaxkey:
            break;
        default:
            assert(false);
        }
        if( (lval&cHASMORE) == 0 )
            break;
    }
    return true;
}
예제 #2
0
inline unsigned sizeOfElement(const unsigned char* p) {
    unsigned type = *p & cCANONTYPEMASK;
    unsigned sz = sizes[type];
    if (sz == 0) {
        if (type == cstring) {
            sz = ((unsigned)p[1]) + 2;
        } else {
            verify(type == cbindata);
            sz = binDataCodeToLength(p[1]) + 2;
        }
    }
    return sz;
}
예제 #3
0
파일: key.cpp 프로젝트: 10genReviews/mongo
    bool KeyV1::woEqual(const KeyV1& right) const {
        const unsigned char *l = _keyData;
        const unsigned char *r = right._keyData;

        if( (*l|*r) == IsBSON ) {
            return toBson().equal(right.toBson());
        }

        while( 1 ) { 
            char lval = *l; 
            char rval = *r;
            if( (lval&(cCANONTYPEMASK|cHASMORE)) != (rval&(cCANONTYPEMASK|cHASMORE)) )
                return false;
            l++; r++;
            switch( lval&cCANONTYPEMASK ) { 
            case coid:
                if( *((unsigned*) l) != *((unsigned*) r) )
                    return false;
                l += 4; r += 4;
            case cdate:
                if( *((unsigned long long *) l) != *((unsigned long long *) r) )
                    return false;
                l += 8; r += 8;
                break;
            case cdouble:
                if( (reinterpret_cast< const PackedDouble* > (l))->d != (reinterpret_cast< const PackedDouble* >(r))->d )
                    return false;
                l += 8; r += 8;
                break;
            case cstring:
                {
                    if( *l != *r ) 
                        return false; // not same length
                    unsigned sz = ((unsigned) *l) + 1;
                    if( memcmp(l, r, sz) )
                        return false;
                    l += sz; r += sz;
                    break;
                }
            case cbindata:
                {
                    if( *l != *r )
                        return false; // len or subtype mismatch
                    int len = binDataCodeToLength(*l) + 1;
                    if( memcmp(l, r, len) ) 
                        return false;
                    l += len; r += len;
                    break;
                }
            case cminkey:
            case cnull:
            case cfalse:
            case ctrue:
            case cmaxkey:
                break;
            default:
                verify(false);
            }
            if( (lval&cHASMORE) == 0 )
                break;
        }
        return true;
    }
예제 #4
0
파일: key.cpp 프로젝트: 10genReviews/mongo
    static int compare(const unsigned char *&l, const unsigned char *&r) { 
        int lt = (*l & cCANONTYPEMASK);
        int rt = (*r & cCANONTYPEMASK);
        int x = lt - rt;
        if( x ) 
            return x;

        l++; r++;

        // same type
        switch( lt ) { 
        case cdouble:
            {
                double L = (reinterpret_cast< const PackedDouble* >(l))->d;
                double R = (reinterpret_cast< const PackedDouble* >(r))->d;
                if( L < R )
                    return -1;
                if( L != R )
                    return 1;
                l += 8; r += 8;
                break;
            }
        case cstring:
            {
                int lsz = *l;
                int rsz = *r;
                int common = min(lsz, rsz);
                l++; r++; // skip the size byte
                // use memcmp as we (will) allow zeros in UTF8 strings
                int res = memcmp(l, r, common);
                if( res ) 
                    return res;
                // longer string is the greater one
                int diff = lsz-rsz;
                if( diff ) 
                    return diff;
                l += lsz; r += lsz;
                break;
            }
        case cbindata:
            {
                int L = *l;
                int R = *r;
                int llen = binDataCodeToLength(L);
                int diff = L-R; // checks length and subtype simultaneously
                if( diff ) {
                    // unfortunately nibbles are backwards to do subtype and len in one check (could bit swap...)
                    int rlen = binDataCodeToLength(R);
                    if( llen != rlen ) 
                        return llen - rlen;
                    return diff;
                }
                // same length, same type
                l++; r++;
                int res = memcmp(l, r, llen);
                if( res ) 
                    return res;
                l += llen; r += llen;
                break;
            }
        case cdate:
            {
                long long L = *((long long *) l);
                long long R = *((long long *) r);
                if( L < R )
                    return -1;
                if( L > R )
                    return 1;
                l += 8; r += 8;
                break;
            }
        case coid:
            {
                int res = memcmp(l, r, sizeof(OID));
                if( res ) 
                    return res;
                l += 12; r += 12;
                break;
            }
        default:
            // all the others are a match -- e.g. null == null
            ;
        }

        return 0;
    }
예제 #5
0
파일: key.cpp 프로젝트: 10genReviews/mongo
    BSONObj KeyV1::toBson() const { 
        verify( _keyData != 0 );
        if( !isCompactFormat() )
            return bson();

        BSONObjBuilder b(512);
        const unsigned char *p = _keyData;
        while( 1 ) { 
            unsigned bits = *p++;

            switch( bits & 0x3f ) {
                case cminkey: b.appendMinKey(""); break;
                case cnull:   b.appendNull(""); break;
                case cfalse:  b.appendBool("", false); break;
                case ctrue:   b.appendBool("", true); break;
                case cmaxkey: 
                    b.appendMaxKey(""); 
                    break;
                case cstring:
                    {
                        unsigned sz = *p++;
                        // we build the element ourself as we have to null terminate it
                        BufBuilder &bb = b.bb();
                        bb.appendNum((char) String);
                        bb.appendUChar(0); // fieldname ""
                        bb.appendNum(sz+1);
                        bb.appendBuf(p, sz);
                        bb.appendUChar(0); // null char at end of string
                        p += sz;
                        break;
                    }
                case coid:
                    b.appendOID("", (OID *) p);
                    p += sizeof(OID);
                    break;
                case cbindata:
                    {
                        int len = binDataCodeToLength(*p);
                        int subtype = (*p) & BinDataTypeMask;
                        if( subtype & 0x8 ) { 
                            subtype = (subtype & 0x7) | 0x80;
                        }
                        b.appendBinData("", len, (BinDataType) subtype, ++p);
                        p += len;
                        break;
                    }
                case cdate:
                    b.appendDate("", (Date_t&) *p);
                    p += 8;
                    break;
                case cdouble:
                    b.append("", (double&) *p);
                    p += sizeof(double);
                    break;
                case cint:
                    b.append("", static_cast< int >((reinterpret_cast< const PackedDouble& >(*p)).d));
                    p += sizeof(double);
                    break;
                case clong:
                    b.append("", static_cast< long long>((reinterpret_cast< const PackedDouble& >(*p)).d));
                    p += sizeof(double);
                    break;
                default:
                    verify(false);
            }

            if( (bits & cHASMORE) == 0 )
                break;
        }
        return b.obj();
    }
예제 #6
0
파일: key.cpp 프로젝트: RalphSu/mongo
        static int compare(const unsigned char *&l, const unsigned char *&r) {
            int lt_real = (*l & cFULLTYPEMASK);
            int rt_real = (*r & cFULLTYPEMASK);
            int lt = (lt_real & cCANONTYPEMASK);
            int rt = (rt_real & cCANONTYPEMASK);
            int x = lt - rt;
            if( x ) 
                return x;

            l++; r++;

            // same type
            switch( lt ) { 
            case cdouble:
                {
                    if (unlikely(lt_real == cint64 && rt_real == cint64)) {
                        long long L = *reinterpret_cast<const long long *>(l);
                        long long R = *reinterpret_cast<const long long *>(r);
                        if (L < R) {
                            return -1;
                        }
                        if (L != R) {
                            return 1;
                        }
                    } else {
                        // We only pack numbers as cint64 if they are larger than the largest thing
                        // we would store as a double.  However, user inputted doubles can be larger
                        // than 2^52 and just be packed as doubles because they came that way, so we
                        // need to actually do the comparison, not just take the one that's packed
                        // as an int to be greater or lesser.
                        double L = (unlikely(lt_real == cint64)
                                    ? double(*reinterpret_cast<const long long *>(l))
                                    : (reinterpret_cast<const PackedDouble *>(l))->d);
                        double R = (unlikely(rt_real == cint64)
                                    ? double(*reinterpret_cast<const long long *>(r))
                                    : (reinterpret_cast<const PackedDouble *>(r))->d);
                        if (L < R) {
                            return -1;
                        }
                        if (L != R) {
                            return 1;
                        }
                    }
                    l += 8; r += 8;
                    break;
                }
            case cstring:
                {
                    int lsz = *l;
                    int rsz = *r;
                    int common = min(lsz, rsz);
                    l++; r++; // skip the size byte
                    // use memcmp as we (will) allow zeros in UTF8 strings
                    int res = memcmp(l, r, common);
                    if( res ) 
                        return res;
                    // longer string is the greater one
                    int diff = lsz-rsz;
                    if( diff ) 
                        return diff;
                    l += lsz; r += lsz;
                    break;
                }
            case cbindata:
                {
                    int L = *l;
                    int R = *r;
                    int llen = binDataCodeToLength(L);
                    int diff = L-R; // checks length and subtype simultaneously
                    if( diff ) {
                        // unfortunately nibbles are backwards to do subtype and len in one check (could bit swap...)
                        int rlen = binDataCodeToLength(R);
                        if( llen != rlen ) 
                            return llen - rlen;
                        return diff;
                    }
                    // same length, same type
                    l++; r++;
                    int res = memcmp(l, r, llen);
                    if( res ) 
                        return res;
                    l += llen; r += llen;
                    break;
                }
            case cdate:
                {
                    long long L = *((long long *) l);
                    long long R = *((long long *) r);
                    if( L < R )
                        return -1;
                    if( L > R )
                        return 1;
                    l += 8; r += 8;
                    break;
                }
            case coid:
                {
                    int res = memcmp(l, r, sizeof(OID));
                    if( res ) 
                        return res;
                    l += 12; r += 12;
                    break;
                }
            default:
                // all the others are a match -- e.g. null == null
                ;
            }

            return 0;
        }
예제 #7
0
파일: key.cpp 프로젝트: kzys/mongo
static int compare(const unsigned char *&l, const unsigned char *&r) {
    int lt = (*l & cCANONTYPEMASK);
    int rt = (*r & cCANONTYPEMASK);
    int x = lt - rt;
    if( x )
        return x;

    l++;
    r++;

    // same type
    switch( lt ) {
    case cdouble:
    {
        double L = *((double *) l);
        double R = *((double *) r);
        if( L < R )
            return -1;
        if( L > R )
            return 1;
        l += 8;
        r += 8;
        break;
    }
    case cstring:
    {
        int lsz = *l;
        int rsz = *r;
        int common = min(lsz, rsz);
        l++;
        r++; // skip the size byte
        // use memcmp as we (will) allow zeros in UTF8 strings
        int res = memcmp(l, r, common);
        if( res )
            return res;
        // longer string is the greater one
        int diff = lsz-rsz;
        if( diff )
            return diff;
        l += lsz;
        r += lsz;
        break;
    }
    case coid:
    {
        int res = memcmp(l, r, sizeof(OID));
        if( res )
            return res;
        l += 12;
        r += 12;
        break;
    }
    case cbindata:
    {
        int L = *l;
        int R = *r;
        int diff = L-R; // checks length and subtype simultaneously
        if( diff )
            return diff;
        // same length, same type
        l++;
        r++;
        int len = binDataCodeToLength(L);
        int res = memcmp(l, r, len);
        if( res )
            return res;
        l += len;
        r += len;
        break;
    }
    case cdate:
    {
        long long L = *((long long *) l);
        long long R = *((long long *) r);
        if( L < R )
            return -1;
        if( L > R )
            return 1;
        l += 8;
        r += 8;
        break;
    }
    default:
        // all the others are a match -- e.g. null == null
        ;
    }

    return 0;
}