Ejemplo n.º 1
0
int CollateJSON(const sized_buf *buf1,
                const sized_buf *buf2,
                CollateJSONMode mode)
{
    const char* str1 = buf1->buf;
    const char* str2 = buf2->buf;
    int depth = 0;

    do {
        /* Get the types of the next token in each string: */
        ValueType type1 = valueTypeOf(*str1);
        ValueType type2 = valueTypeOf(*str2);
        /* If types don't match, stop and return their relative ordering: */
        if (type1 != type2) {
            if (mode != kCollateJSON_Raw)
                return cmp(type1, type2);
            else
                return cmp(kRawOrderOfValueType[type1], kRawOrderOfValueType[type2]);

        /* If types match, compare the actual token values: */
        } else switch (type1) {
            case kNull:
            case kTrue:
                str1 += 4;
                str2 += 4;
                break;
            case kFalse:
                str1 += 5;
                str2 += 5;
                break;
            case kNumber: {
                char* next1, *next2;
                int diff;
                if (depth == 0) {
                    /* At depth 0, be careful not to fall off the end of the
                       input, because there won't be any delimiters (']' or
                       '}') after the number! */
                    diff = dcmp( readNumber(str1, buf1->buf + buf1->size, &next1),
                                 readNumber(str2, buf2->buf + buf2->size, &next2) );
                } else {
                    diff = dcmp( strtod(str1, &next1), strtod(str2, &next2) );
                }
                if (diff)
                    return diff; /* Numbers don't match */
                str1 = next1;
                str2 = next2;
                break;
            }
            case kString: {
                int diff;
                if (mode == kCollateJSON_Unicode)
                    diff = compareStringsUnicode(&str1, &str2);
                else
                    diff = compareStringsASCII(&str1, &str2);
                if (diff)
                    return diff; /* Strings don't match */
                break;
            }
            case kArray:
            case kObject:
                ++str1;
                ++str2;
                ++depth;
                break;
            case kEndArray:
            case kEndObject:
                ++str1;
                ++str2;
                --depth;
                break;
            case kComma:
            case kColon:
                ++str1;
                ++str2;
                break;
            case kIllegal:
                return 0;
        }
    /* Keep going as long as we're inside an array or object */
    } while (depth > 0);
    return 0;
}
int CollateJSON(void *context, int len1, const void * chars1, int len2, const void * chars2) {
    
    static bool charPriorityMapInitialized = false;
    if(!charPriorityMapInitialized){
        initializeCharPriorityMap();
        charPriorityMapInitialized = true;
    }
    
    const char* str1 = (const char*) chars1;
    const char* str2 = (const char*) chars2;
    int depth = 0;
    
    do {
        
        // Get the types of the next token in each string:
        ValueType type1 = valueTypeOf(*str1);
        ValueType type2 = valueTypeOf(*str2);
        // If types don't match, stop and return their relative ordering:
        if (type1 != type2) {
            if (context != kJsonCollator_Raw)
                return cmp(type1, type2);
            else
                return cmp(kRawOrderOfValueType[type1],
                           kRawOrderOfValueType[type2]);
            
            // If types match, compare the actual token values:
        } else
            switch (type1) {
                case kNull:
                case kTrue:
                    str1 += 4;
                    str2 += 4;
                    break;
                case kFalse:
                    str1 += 5;
                    str2 += 5;
                    break;
                case kNumber: {
                    char* next1, *next2;
                    int diff;
                    if (depth == 0) {
                        diff = dcmp( readNumber(str1, str1 + len1, &next1),
                                    readNumber(str2, str2 + len2, &next2) );
                    } else {
                        diff = dcmp(strtod(str1, &next1), strtod(str2, &next2));
                    }
                    if (diff) {
                        return diff; // Numbers don't match
                    }
                    str1 = next1;
                    str2 = next2;
                    break;
                }
                case kString: {
                    int diff;
                    if (context == kJsonCollator_Unicode)
                        diff = compareStringsUnicode(&str1, &str2);
                    else
                        diff = compareStringsASCII(&str1, &str2);
                    if (diff)
                        return diff; // Strings don't match
                    break;
                }
                case kArray:
                case kObject:
                    ++str1;
                    ++str2;
                    ++depth;
                    break;
                case kEndArray:
                case kEndObject:
                    ++str1;
                    ++str2;
                    --depth;
                    break;
                case kComma:
                case kColon:
                    ++str1;
                    ++str2;
                    break;
                case kIllegal:
                    return 0;
            }
    } while (depth > 0); // Keep going as long as we're inside an array or object
    return 0;
}