void AccessorDeserialize( Formatter& formatter, void* obj, const ClassAccessors& props) { using Blob = Formatter::Blob; using CharType = Formatter::value_type; auto charTypeCat = ImpliedTyping::TypeOf<CharType>()._type; for (;;) { switch (formatter.PeekNext()) { case Blob::AttributeName: { typename Formatter::InteriorSection name, value; if (!formatter.TryAttribute(name, value)) Throw(FormatException("Error in begin element", formatter.GetLocation())); auto arrayBracket = std::find(name._start, name._end, '['); if (arrayBracket == name._end) { if (!props.TryOpaqueSet( obj, Hash64(name._start, name._end), value._start, ImpliedTyping::TypeDesc(charTypeCat, uint16(value._end - value._start)), true)) { LogWarning << "Failure while assigning property during deserialization -- " << Conversion::Convert<std::string>(std::basic_string<CharType>(name._start, name._end)); } } else { auto arrayIndex = XlAtoUI32((const char*)(arrayBracket+1)); if (!props.TryOpaqueSet( obj, Hash64(name._start, arrayBracket), arrayIndex, value._start, ImpliedTyping::TypeDesc(charTypeCat, uint16(value._end - value._start)), true)) { LogWarning << "Failure while assigning array property during deserialization -- " << Conversion::Convert<std::string>(std::basic_string<CharType>(name._start, name._end)); } } } break; case Blob::EndElement: case Blob::None: return; case Blob::BeginElement: { typename Formatter::InteriorSection eleName; if (!formatter.TryBeginElement(eleName)) Throw(FormatException("Error in begin element", formatter.GetLocation())); auto created = props.TryCreateChild(obj, Hash64(eleName._start, eleName._end)); if (created.first) { AccessorDeserialize(formatter, created.first, *created.second); } else { LogWarning << "Couldn't find a match for element name during deserialization -- " << Conversion::Convert<std::string>(std::basic_string<CharType>(eleName._start, eleName._end)); formatter.SkipElement(); } if (!formatter.TryEndElement()) Throw(FormatException("Expecting end element", formatter.GetLocation())); break; } } } }