예제 #1
0
static bool DecodeField(DecodeState& ds, TxtNode *firstNode, TxtNode *defaultFirstNode, FieldMetadata *fieldDef, uint8_t *structDataStart)
{
    Type type = fieldDef->type;
    uint8_t *structDataPtr = structDataStart + fieldDef->offset;

    if ((type & TYPE_NO_STORE_MASK) != 0) {
        WriteDefaultValue(structDataPtr, type);
        return true;
    }

    bool isCompact = ((type & TYPE_STORE_COMPACT_MASK) != 0);
    type = (Type)(type & TYPE_NO_FLAGS_MASK);

    const char *fieldName = ds.fieldNamesSeq + fieldDef->nameOffset;
    size_t fieldNameLen = str::Len(fieldName);
    TxtNode *dataNode = FindNode(firstNode, fieldName, fieldNameLen);
    TxtNode *defaultNode = FindNode(defaultFirstNode, fieldName, fieldNameLen);

    // if the node doesn't exist in data, try to get it from default data
    TxtNode *node = dataNode ? dataNode : defaultNode;
    if (!node) {
        WriteDefaultValue(structDataPtr, type);
        return true;
    }
    bool ok;
    if (TYPE_BOOL == type) {
        bool bVal;
        ok = ParseBool(node->valStart, node->valEnd, &bVal);
        if (!ok)
            return false;
        WriteStructBool(structDataPtr, bVal);
    } else if (TYPE_COLOR == type) {
        COLORREF val;
        ok = ParseColor(node->valStart, node->valEnd, &val);
        if (ok)
            WriteStructUInt(structDataPtr, TYPE_COLOR, val);
    } else if (IsUnsignedIntType(type)) {
        uint64_t n;
        ok = ParseUInt(node->valStart, node->valEnd, &n);
        if (ok)
            ok = WriteStructUInt(structDataPtr, type, n);
    } else if (IsSignedIntType(type)) {
        int64_t n;
        ok = ParseInt(node->valStart, node->valEnd, &n);
        if (ok)
            ok = WriteStructInt(structDataPtr, type, n);
    } else if (TYPE_STRUCT_PTR == type) {
        uint8_t *d = NULL;
        if (isCompact && (TextNode == node->type)) {
            d = DeserializeCompact(ds, node, defaultNode, fieldDef->def);
        } else {
            if (StructNode != node->type)
                return false;
            d = DeserializeRec(ds, node, defaultNode, fieldDef->def);
        }
        if (!d)
            goto Error;
        WriteStructPtrVal(structDataPtr, d);
    } else if (TYPE_STR == type) {
        char *s = node->valStart;
        size_t sLen = node->valEnd - s;
        if (s && (sLen > 0)) {
            // note: we don't free s because it's remembered in structDataPtr
            s = str::DupN(s, sLen);
            WriteStructStr(structDataPtr, s);
        }
    } else if (TYPE_WSTR == type) {
        char *s = node->valStart;
        size_t sLen = node->valEnd - s;
        if (s && (sLen > 0)) {
            // note: we don't free ws because it's remembered in structDataPtr
            WCHAR *ws = str::conv::FromUtf8(s);
            WriteStructWStr(structDataPtr, ws);
        }
    }  else if (TYPE_FLOAT == type) {
        float f;
        ok = ParseFloat(node->valStart, node->valEnd, &f);
        if (ok)
            WriteStructFloat(structDataPtr, f);
    } else if (TYPE_ARRAY == type) {
        CrashIf(!fieldDef->def); // array elements must be a struct
        if (StructNode != node->type)
            return false;
        TxtNode *child;
        ListNode<void> *last = NULL;
        for (size_t i = 0; i < node->children->Count(); i++) {
            child = node->children->At(i);
            if (ArrayNode != child->type)
                return false;
            uint8_t *d = DeserializeRec(ds, child, NULL, fieldDef->def);
            if (!d)
                goto Error; // TODO: free root
            ListNode<void> *tmp = AllocArray<ListNode<void>>(1);
            tmp->val = (void*)d;
            if (!last) {
                // this is root
                last = tmp;
                // we remember it so that it gets freed in case of error
                WriteStructPtrVal(structDataPtr, (void*)last);
            } else {
                last->next = tmp;
                last = tmp;
            }
        }
    } else {
        CrashIf(true);
        return false;
    }
    return true;
Error:
    return false;
}
예제 #2
0
static bool DecodeField(DecodeState& ds, TxtNode *firstNode, const char *fieldName, const FieldMetadata *fieldDef, uint8_t *structDataStart)
{
    Type type = fieldDef->type;
    uint8_t *structDataPtr = structDataStart + fieldDef->offset;

    if ((type & TYPE_NO_STORE_MASK) != 0) {
        WriteDefaultValue(structDataPtr, type);
        return true;
    }

    bool isCompact = ((type & TYPE_STORE_COMPACT_MASK) != 0);
    type = (Type)(type & TYPE_MASK);

    size_t fieldNameLen = str::Len(fieldName);

    // if the node doesn't exist in data, try to get it from default data
    TxtNode *node = FindNode(firstNode, fieldName, fieldNameLen);
    if (!node) {
        WriteDefaultValue(structDataPtr, type);
        return true;
    }
    bool ok;
    if (TYPE_BOOL == type) {
        bool bVal;
        ok = ParseBool(node->valStart, node->valEnd, &bVal);
        if (!ok)
            return false;
        WriteStructBool(structDataPtr, bVal);
    } else if (TYPE_COLOR == type) {
        COLORREF val;
        ok = ParseColor(node->valStart, node->valEnd, &val);
        if (ok)
            WriteStructUInt(structDataPtr, TYPE_COLOR, val);
    } else if (IsUnsignedIntType(type)) {
        uint64_t n;
        ok = ParseUInt(node->valStart, node->valEnd, &n);
        if (ok)
            ok = WriteStructUInt(structDataPtr, type, n);
    } else if (IsSignedIntType(type)) {
        int64_t n;
        ok = ParseInt(node->valStart, node->valEnd, &n);
        if (ok)
            ok = WriteStructInt(structDataPtr, type, n);
    } else if (TYPE_STRUCT_PTR == type) {
        uint8_t *d = DecodeStruct(ds, fieldDef, node, isCompact);
        if (d)
            WriteStructPtrVal(structDataPtr, d);
    } else if (TYPE_STR == type) {
        char *s = node->valStart;
        size_t sLen = node->valEnd - s;
        if (s && (sLen > 0)) {
            // note: we don't free s because it's remembered in structDataPtr
            s = str::DupN(s, sLen);
            WriteStructStr(structDataPtr, s);
        }
    } else if (TYPE_WSTR == type) {
        char *s = node->valStart;
        size_t sLen = node->valEnd - s;
        if (s && (sLen > 0)) {
            // note: we don't free ws because it's remembered in structDataPtr
            WCHAR *ws = str::conv::FromUtf8(s);
            WriteStructWStr(structDataPtr, ws);
        }
    }  else if (TYPE_FLOAT == type) {
        float f;
        ok = ParseFloat(node->valStart, node->valEnd, &f);
        if (ok)
            WriteStructFloat(structDataPtr, f);
    } else if (TYPE_ARRAY == type) {
        if (StructNode != node->type)
            return false;
        Vec<uint8_t*> *vec = new Vec<uint8_t*>();
        // we remember it right away, so that it gets freed in case of error
        WriteStructPtrVal(structDataPtr, (void*)vec);
        TxtNode *child;
        for (size_t i = 0; i < node->children->Count(); i++) {
            child = node->children->At(i);
            uint8_t *d = DecodeStruct(ds, fieldDef, child, isCompact);
            if (d)
                vec->Append(d);
        }
    } else {
        CrashIf(true);
        return false;
    }
    return true;
}