static uint8_t *DeserializeCompact(DecodeState& ds, TxtNode *node, const StructMetadata *structDef) { CrashIf(TextNode != node->type); TxtNode *structNode = StructNodeFromTextNode(ds, node, structDef); if (!structNode) return NULL; uint8_t *res = DeserializeRec(ds, structNode, structDef); FreeTxtNode(structNode); return res; }
static uint8_t *DecodeStruct(DecodeState& ds, const FieldMetadata *fieldDef, TxtNode *node, bool isCompact) { uint8_t *d = NULL; if (isCompact && (TextNode == node->type)) { d = DeserializeCompact(ds, node, GetStructDef(fieldDef)); } else { if (StructNode == node->type) d = DeserializeRec(ds, node, GetStructDef(fieldDef)); } return d; }
uint8_t* Deserialize(char *data, size_t dataSize, const StructMetadata *def) { if (!data) return NULL; DecodeState ds; ds.parser.SetToParse(data, dataSize); bool ok = ParseTxt(ds.parser); if (!ok) return NULL; return DeserializeRec(ds, ds.parser.nodes.At(0), def); }
// data and defaultData is in text format. we might modify it in place uint8_t* DeserializeWithDefault(char *data, size_t dataSize, char *defaultData, size_t defaultDataSize, StructMetadata *def, const char *fieldNamesSeq) { if (!data) return NULL; DecodeState ds; ds.fieldNamesSeq = fieldNamesSeq; ds.parser.SetToParse(data, dataSize); bool ok = ParseTxt(ds.parser); if (!ok) return NULL; TxtNode *defaultFirstNode = NULL; DecodeState ds2; ds2.fieldNamesSeq = fieldNamesSeq; ds2.parser.SetToParse(defaultData, defaultDataSize); ok = ParseTxt(ds2.parser); if (ok) defaultFirstNode = ds2.parser.nodes.At(0); return DeserializeRec(ds, ds.parser.nodes.At(0), defaultFirstNode, def); }
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; }
uint8_t* Deserialize(struct TxtNode *root, const StructMetadata *def) { DecodeState ds; return DeserializeRec(ds, root, def); }