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; }
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; }