Advertisement
expired6978

Papyrus Serialize

Apr 13th, 2017
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.63 KB | None | 0 0
  1. #include "f4se/PapyrusSerialization.h"
  2.  
  3. #include "f4se/PapyrusArgs.h"
  4.  
  5. namespace Serialization
  6. {
  7.     bool WriteVMData(const F4SESerializationInterface* intfc, const VMValue * val)
  8.     {
  9.         UInt8 typeId = val->GetTypeEnum();
  10.         if(!WriteData(intfc, &typeId))
  11.             return false;
  12.  
  13.         switch(typeId)
  14.         {
  15.         case VMValue::kType_Identifier:
  16.             {
  17.                 UInt64 handle = 0;
  18.                 BSFixedString typeName;
  19.  
  20.                 VMIdentifier * id = val->data.id;
  21.                 if(id) {
  22.                     handle = id->GetHandle();
  23.                     VMObjectTypeInfo * typeObject = id->m_typeInfo;
  24.                     if(typeObject)
  25.                         typeName = typeObject->m_typeName;
  26.                 }
  27.  
  28.                 if(!WriteData(intfc, &typeName))
  29.                     return false;
  30.                 if(!WriteData(intfc, &handle))
  31.                     return false;
  32.             }
  33.             break;
  34.         case VMValue::kType_String:
  35.             {
  36.                 if(!WriteData(intfc, val->data.GetStr()))
  37.                     return false;
  38.             }
  39.             break;
  40.         case VMValue::kType_Int:
  41.             {
  42.                 if(!WriteData(intfc, &val->data.i))
  43.                     return false;
  44.             }
  45.             break;
  46.         case VMValue::kType_Float:
  47.             {
  48.                 if(!WriteData(intfc, &val->data.f))
  49.                     return false;
  50.             }
  51.             break;
  52.         case VMValue::kType_Bool:
  53.             {
  54.                 if(!WriteData(intfc, &val->data.b))
  55.                     return false;
  56.             }
  57.             break;
  58.         case VMValue::kType_Variable:
  59.             {
  60.                 if(!WriteVMData(intfc, val->data.var))
  61.                     return false;
  62.             }
  63.             break;
  64.         case VMValue::kType_Struct:
  65.             {
  66.                 VMValue::StructData * strct = val->data.strct;
  67.                 VMValue * entries = strct->GetStruct();
  68.                 VMStructTypeInfo * typeObject = strct->m_type;
  69.                 UInt32 members = typeObject->m_members.Size();
  70.  
  71.                 if(!WriteData(intfc, &typeObject->m_typeName))
  72.                     return false;
  73.  
  74.                 if(!WriteData(intfc, &members))
  75.                     return false;
  76.  
  77.                 typeObject->m_members.ForEach([&intfc, &entries](VMStructTypeInfo::MemberItem * item)
  78.                 {
  79.                     WriteData(intfc, &item->name);              // Write Key
  80.                     WriteVMData(intfc, &entries[item->index]);  // Write Value
  81.                     return true;
  82.                 });
  83.             }
  84.             break;
  85.         case VMValue::kType_IdentifierArray:
  86.             {
  87.                 UInt32 length = 0;
  88.                 VMValue::ArrayData * arr = val->data.arr;
  89.                 if(arr) {
  90.                     length = arr->arr.count;
  91.                 }
  92.  
  93.                 if(!WriteData(intfc, &length))
  94.                     return false;
  95.  
  96.                 BSFixedString typeName;
  97.                 IComplexType * typeObject = val->GetComplexType();
  98.                 if(typeObject) {
  99.                     typeName = typeObject->m_typeName;
  100.                 }
  101.  
  102.                 if(!WriteData(intfc, &typeObject->m_typeName))
  103.                     return false;
  104.  
  105.                 if(arr)
  106.                 {
  107.                     for(UInt32 i = 0; i < length; i++)
  108.                     {
  109.                         VMValue entry;
  110.                         arr->arr.GetNthItem(i, entry);
  111.  
  112.                         UInt64 handle = 0;
  113.                         VMIdentifier * id = entry.data.id;
  114.                         if(id) {
  115.                             handle = id->GetHandle();
  116.                         }
  117.  
  118.                         if(!WriteData(intfc, &handle))
  119.                             return false;
  120.                     }
  121.                 }
  122.             }
  123.             break;
  124.         case VMValue::kType_StringArray:
  125.         case VMValue::kType_IntArray:
  126.         case VMValue::kType_FloatArray:
  127.         case VMValue::kType_BoolArray:
  128.             {
  129.                 UInt32 length = 0;
  130.                 VMValue::ArrayData * arr = val->data.arr;
  131.                 if(arr) {
  132.                     length = arr->arr.count;
  133.                 }
  134.  
  135.                 if(!WriteData(intfc, &length))
  136.                     return false;
  137.  
  138.                 if(arr)
  139.                 {
  140.                     for(UInt32 i = 0; i < length; i++)
  141.                     {
  142.                         VMValue entry;
  143.                         arr->arr.GetNthItem(i, entry);
  144.                         switch(typeId) {
  145.                         case VMValue::kType_StringArray:
  146.                             if(!WriteData(intfc, entry.data.GetStr()))
  147.                                 return false;
  148.                             break;
  149.                         case VMValue::kType_IntArray:
  150.                             if(!WriteData(intfc, &entry.data.i))
  151.                                 return false;
  152.                             break;
  153.                         case VMValue::kType_FloatArray:
  154.                             if(!WriteData(intfc, &entry.data.f))
  155.                                 return false;
  156.                             break;
  157.                         case VMValue::kType_BoolArray:
  158.                             if(!WriteData(intfc, &entry.data.b))
  159.                                 return false;
  160.                             break;
  161.                         }
  162.                     }
  163.                 }
  164.             }
  165.             break;
  166.         case VMValue::kType_VariableArray:
  167.             {
  168.                 UInt32 length = 0;
  169.                 VMValue::ArrayData * arr = val->data.arr;
  170.                 if(arr) {
  171.                     length = arr->arr.count;
  172.                 }
  173.  
  174.                 if(!WriteData(intfc, &length))
  175.                     return false;
  176.  
  177.                 if(arr)
  178.                 {
  179.                     for(UInt32 i = 0; i < length; i++)
  180.                     {
  181.                         VMValue entry;
  182.                         arr->arr.GetNthItem(i, entry);
  183.  
  184.                         if(!WriteVMData(intfc, &entry))
  185.                             return false;
  186.                     }
  187.                 }
  188.             }
  189.             break;
  190.         case VMValue::kType_StructArray:
  191.             {
  192.                 UInt32 length = 0;
  193.                 VMValue::ArrayData * arr = val->data.arr;
  194.                 IComplexType * typeArrObject = val->GetComplexType();
  195.                 if(arr) {
  196.                     length = arr->arr.count;
  197.                 }
  198.  
  199.                 BSFixedString typeName;
  200.                 VMStructTypeInfo * typeObject = nullptr;
  201.                 if(typeArrObject && typeArrObject->GetType() == VMValue::kType_Struct) {
  202.                     typeObject = static_cast<VMStructTypeInfo *>(typeArrObject);
  203.                     typeName = typeObject->m_typeName;
  204.                 }
  205.  
  206.                 if(!WriteData(intfc, &length))
  207.                     return false;
  208.  
  209.                 if(!WriteData(intfc, &typeName))
  210.                     return false;
  211.  
  212.                 UInt32 members = typeObject ? typeObject->m_members.Size() : 0;
  213.                 if(!WriteData(intfc, &members))
  214.                     return false;
  215.  
  216.                 for(UInt32 i = 0; i < length; i++)
  217.                 {
  218.                     VMValue entry;
  219.                     arr->arr.GetNthItem(i, entry);
  220.  
  221.                     VMValue::StructData * strct = entry.data.strct;
  222.                     VMValue * entries = strct->GetStruct();
  223.                     if(typeObject)
  224.                     {
  225.                         typeObject->m_members.ForEach([&intfc, &entries](VMStructTypeInfo::MemberItem * item)
  226.                         {
  227.                             WriteData(intfc, &item->name);              // Write Key
  228.                             WriteVMData(intfc, &entries[item->index]);  // Write Value
  229.                             return true;
  230.                         });
  231.                     }
  232.                 }
  233.             }
  234.             break;
  235.         }
  236.         return true;
  237.     }
  238.  
  239.     bool ReadVMData(const F4SESerializationInterface* intfc, VMValue * val)
  240.     {
  241.         VirtualMachine * vm = (*g_gameVM)->m_virtualMachine;
  242.  
  243.         UInt8 typeId = 0;
  244.         if(!ReadData(intfc, &typeId))
  245.             return false;
  246.  
  247.         switch(typeId)
  248.         {
  249.         case VMValue::kType_Identifier:
  250.             {
  251.                 BSFixedString typeName;
  252.                 if(!ReadData(intfc, &typeName))
  253.                     return false;
  254.  
  255.                 UInt64 handle = 0;
  256.                 if(!ReadData(intfc, &handle))
  257.                     return false;
  258.  
  259.                 if(intfc->ResolveHandle(handle, &handle)) {
  260.                     GetIdentifier(val, handle, &typeName, vm);
  261.                 }
  262.             }
  263.             break;
  264.         case VMValue::kType_String:
  265.             {
  266.                 BSFixedString str;
  267.                 if(!ReadData(intfc, &str))
  268.                     return false;
  269.                 val->SetString(str);
  270.             }
  271.             break;
  272.         case VMValue::kType_Int:
  273.             {
  274.                 SInt32 i = 0;
  275.                 if(!ReadData(intfc, &i))
  276.                     return false;
  277.                 val->SetInt(i);
  278.             }
  279.             break;
  280.         case VMValue::kType_Float:
  281.             {
  282.                 float f = 0.0f;
  283.                 if(!WriteData(intfc, &f))
  284.                     return false;
  285.                 val->SetFloat(f);
  286.             }
  287.             break;
  288.         case VMValue::kType_Bool:
  289.             {
  290.                 bool b = false;
  291.                 if(!WriteData(intfc, &b))
  292.                     return false;
  293.                 val->SetBool(b);
  294.             }
  295.             break;
  296.         case VMValue::kType_Variable:
  297.             {
  298.                 VMValue * value = new VMValue;
  299.                 if(!ReadVMData(intfc, value)) {
  300.                     delete value;
  301.                     return false;
  302.                 }
  303.                 val->SetVariable(value);
  304.             }
  305.             break;
  306.         case VMValue::kType_Struct:
  307.             {
  308.                 BSFixedString structName;
  309.                 if(!ReadData(intfc, &structName))
  310.                     return false;
  311.  
  312.                 UInt32 members;
  313.                 if(!ReadData(intfc, &members))
  314.                     return false;
  315.  
  316.                 VMStructTypeInfo * typeObject = nullptr;
  317.                 if(vm->GetStructTypeInfo(&structName, &typeObject))
  318.                     if(typeObject)
  319.                         typeObject->Release();
  320.  
  321.                 val->SetComplexType(typeObject);
  322.  
  323.                 // Make sure our type still exists
  324.                 VMValue::StructData * strct = nullptr;
  325.                 if(typeObject)
  326.                     vm->CreateStruct(&structName, &strct);
  327.  
  328.                 for(UInt32 i = 0; i < members; i++)
  329.                 {
  330.                     BSFixedString member;
  331.                     if(!ReadData(intfc, &member))   // Read Key
  332.                         return false;
  333.  
  334.                     VMValue data;
  335.                     if(!ReadVMData(intfc, &data))   // Read Value
  336.                         return false;
  337.  
  338.                     if(strct)
  339.                     {
  340.                         auto memberItem = typeObject->m_members.Find(&member);
  341.                         if(memberItem)
  342.                             strct->GetStruct()[memberItem->index] = data;
  343.                     }
  344.                 }
  345.  
  346.                 val->data.strct = strct;
  347.             }
  348.             break;
  349.         case VMValue::kType_IdentifierArray:
  350.             {
  351.                 UInt32 length = 0;
  352.                 if(!ReadData(intfc, &length))
  353.                     return false;
  354.  
  355.                 BSFixedString typeName;
  356.                 if(!ReadData(intfc, &typeName))
  357.                     return false;
  358.  
  359.                 VMValue::ArrayData * data = nullptr;
  360.                 vm->CreateArray(val, length, &data);
  361.  
  362.                 VMObjectTypeInfo * typeInfo = nullptr;
  363.                 if(vm->GetObjectTypeInfoByName(&typeName, &typeInfo))
  364.                     if(typeInfo)
  365.                         typeInfo->Release();
  366.  
  367.                 for(UInt32 i = 0; i < length; i++)
  368.                 {
  369.                     UInt64 handle = 0;
  370.                     if(!ReadData(intfc, &handle))
  371.                         return false;
  372.  
  373.                     if(intfc->ResolveHandle(handle, &handle) && data) {
  374.                         GetIdentifier(&data->arr.entries[i], handle, typeInfo, (*g_gameVM)->m_virtualMachine);
  375.                     }
  376.                 }
  377.  
  378.                 val->SetComplexType(typeInfo);
  379.                 val->data.arr = data;
  380.             }
  381.             break;
  382.         case VMValue::kType_StringArray:
  383.         case VMValue::kType_IntArray:
  384.         case VMValue::kType_FloatArray:
  385.         case VMValue::kType_BoolArray:
  386.             {
  387.                 UInt32 length = 0;
  388.                 if(!ReadData(intfc, &length))
  389.                     return false;
  390.  
  391.                 VMValue::ArrayData * data = nullptr;
  392.                 vm->CreateArray(val, length, &data);
  393.  
  394.                 val->type.value = typeId;
  395.  
  396.                 for(UInt32 i = 0; i < length; i++)
  397.                 {
  398.                     switch(typeId) {
  399.                     case VMValue::kType_StringArray:
  400.                         {
  401.                             BSFixedString str;
  402.                             if(!ReadData(intfc, &str))
  403.                                 return false;
  404.                             data->arr.entries[i].SetString(str);
  405.                         }
  406.                         break;
  407.                     case VMValue::kType_IntArray:
  408.                         {
  409.                             SInt32 i = 0;
  410.                             if(!ReadData(intfc, &i))
  411.                                 return false;
  412.                             data->arr.entries[i].SetInt(i);
  413.                         }
  414.                         break;
  415.                     case VMValue::kType_FloatArray:
  416.                         {
  417.                             float f = 0.0f;
  418.                             if(!ReadData(intfc, &f))
  419.                                 return false;
  420.                             data->arr.entries[i].SetFloat(f);
  421.                         }
  422.                         break;
  423.                     case VMValue::kType_BoolArray:
  424.                         {
  425.                             bool b = false;
  426.                             if(!ReadData(intfc, &b))
  427.                                 return false;
  428.                             data->arr.entries[i].SetBool(b);
  429.                         }
  430.                         break;
  431.                     }
  432.                 }
  433.             }
  434.             break;
  435.         case VMValue::kType_VariableArray:
  436.             {
  437.                 UInt32 length = 0;
  438.                 if(!WriteData(intfc, &length))
  439.                     return false;
  440.  
  441.                 VMValue::ArrayData * data = nullptr;
  442.                 vm->CreateArray(val, length, &data);
  443.  
  444.                 val->type.value = typeId;
  445.  
  446.                 for(UInt32 i = 0; i < length; i++)
  447.                 {
  448.                     if(!ReadVMData(intfc, &data->arr.entries[i]))
  449.                         return false;
  450.                 }
  451.             }
  452.             break;
  453.         case VMValue::kType_StructArray:
  454.             {
  455.                 UInt32 length = 0;
  456.                 if(!ReadData(intfc, &length))
  457.                     return false;
  458.  
  459.                 BSFixedString structName;
  460.                 if(!ReadData(intfc, &structName))
  461.                     return false;
  462.  
  463.                 UInt32 members = 0;
  464.                 if(!ReadData(intfc, &members))
  465.                     return false;
  466.  
  467.                 VMStructTypeInfo * typeObject = nullptr;
  468.                 if(vm->GetStructTypeInfo(&structName, &typeObject))
  469.                     if(typeObject)
  470.                         typeObject->Release();
  471.  
  472.                 if(typeObject)
  473.                     val->SetComplexType(reinterpret_cast<IComplexType*>((UInt64)typeObject | 1));
  474.  
  475.                 // Entire array requires the type
  476.                 VMValue::ArrayData * data = nullptr;
  477.                 if(typeObject)
  478.                     vm->CreateArray(val, length, &data);
  479.  
  480.                 for(UInt32 i = 0; i < length; i++)
  481.                 {
  482.                     VMValue::StructData * strct = nullptr;
  483.                     if(typeObject)
  484.                         vm->CreateStruct(&structName, &strct);
  485.  
  486.                     for(UInt32 j = 0; j < members; j++)
  487.                     {
  488.                         BSFixedString member;
  489.                         if(!ReadData(intfc, &member))   // Read Key
  490.                             return false;
  491.  
  492.                         VMValue data;
  493.                         if(!ReadVMData(intfc, &data))   // Read Value
  494.                             return false;
  495.  
  496.                         // Set the member data if we both had the type and created the struct
  497.                         if(strct) {
  498.                             auto memberItem = typeObject->m_members.Find(&member);
  499.                             if(memberItem)
  500.                                 strct->GetStruct()[memberItem->index] = data;
  501.                         }
  502.                     }
  503.  
  504.                     if(typeObject) {
  505.                         data->arr.entries[i].SetComplexType(typeObject);
  506.                         data->arr.entries[i].data.strct = strct;
  507.                     }
  508.                 }
  509.             }
  510.             break;
  511.         }
  512.         return true;
  513.     }
  514. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement