ArrayDeserialize

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search

A User Function for use with Oblivion Script Extender

Syntax:

(DeserializedArray :array) ArrayDeserialize SerialArray :array

Deserializes a one-dimension StringMap array, converting it back to a multi-dimensional array structure.

The arguments are:

  • Array - the array to deserialize

An array like this:

['EntryA_Attr1'] = 'A' 
['EntryA_Attr1_0_Value1'] = 11
['EntryA_Attr1_0_Value2'] = 22
['EntryA_Attr1_1_Value1'] = 1111
['EntryA_Attr1_1_Value2'] = 2222
['EntryB_Attr1'] = 'B' 
. . . etc

Will become:

['EntryA']
= = ['Attr1'] = 'A' 
= = ['Attr2'] 
= = = = [0] 
= = = = = = ['Value1'] = 11
= = = = = = ['Value2'] = 22
= = = = [1] 
= = = = = = ['Value1'] = 1111
= = = = = = ['Value2'] = 2222
['EntryB']
= = ['Attr1'] = 'B'
= = = = = = . . . etc


Notes[edit | edit source]

  • This function is designed to be used in conjunction with its sister function ArraySerialize
  • A Map type array will be created if the corresponding key part is a number formatted with a decimal point.
  • A Array type array will be created if the corresponding key part is a number formatted without a decimal point.
  • A StringMap type array will be created if the corresponding key part is not a number.
  • The code uses the underscore ('_') as the concatenating char and assumes that it will not be present in any array key or value. Change it to another char if you have underscores in your arrays.
  • StringMap arrays containing numeric strings as keys (like "0005") as the first entry will not convert appropriately.

Usage[edit | edit source]

let MyMultiArray := Call ArrayDeserialize MySerialArray


Code[edit | edit source]

scriptname ArrayDeserialize
;---------------------------------------
array_var arDesSerial 
array_var arKey
array_var arr
array_var asEntry
array_var asParts 
array_var asSerial 
float v
ref reff
short i
string_var s
string_var ss

begin Function {asSerial}

   let arKey := ar_Construct Array    ; used as a generic var to holg either a string or numeric key

   ;---------------------------------------
   ;    Determine the type of the main parent array 
   ;        ( NOTE: based on the first entry !!! )
   ;---------------------------------------
   ;=== Set the key ===
   let s := ar_first asSerial 
   let asParts :=  sv_split s "_"
   let s := asParts[0]
   let v := ToNumber s
   if eval (v != 0) || (s == "0")  || (s == "0.0") 
       ;=== conversion succeeded >> Map or Array ===
       if eval (sv_Find "." s) < 0
           ;=== No period >> Array ===
           let arDesSerial :=  ar_Construct Array
       else
           ;=== Has period >> Map  ===
           let arDesSerial :=  ar_Construct Map
       endif
   else
       ;=== conversion failed >> StringMap ===
       let arDesSerial :=  ar_Construct StringMap
   endif

   foreach asEntry <- asSerial 
       ;=== Start at the top ===
       let arr := arDesSerial 

       ;=== Set the key ===
       let s := asEntry[key]
       let asParts :=  sv_split s "_"

       let i := -1 
       while ( i += 1 ) < (ar_size asParts) - 1    ; all excelp last

           if eval (typeof arr) ==  "StringMap"
               let arKey[0] := asParts[i]
           else
               let arKey[0]  := ToNumber asParts[i]
           endif

           ;=== Move 'arr' one level down ===
           if eval ar_haskey arr arKey[0]
               ;=== branch exists - set arr===
               let arr := arr[arKey[0]]
           else
               ;=== First time, create array based on next key part ===
               let s := asParts[i+1]
               let v := ToNumber s
               if eval (v != 0) || (s == "0")  || (s == "0.0") 
                   ;=== conversion succeeded >> Map or Array ===
                   if eval (sv_Find "." s) < 0
                       ;=== No period >> Array ===
                       let arr[arKey[0]] :=  ar_Construct Array
                   else
                       ;=== Has period >> Map  ===
                       let arr[arKey[0]] :=  ar_Construct Map
                   endif
               else
                   ;=== conversion failed >> StringMap ===
                   let arr[arKey[0]] :=  ar_Construct StringMap
               endif
               let arr := arr[arKey[0]]
           endif
       loop

       ;=== Set the key of the new entry ===
       if eval (typeof arr) ==  "StringMap"
           let arKey[0]  :=asParts[i]
       else
           let arKey[0]  := ToNumber asParts[i]
       endif

       ;=== Set the value of the new entry ===
       let s := asEntry[value]

       if eval (sv_Find "0x" s) == 0
           if eval (sv_length s) > 2
               let s := s[2:(sv_length s) - 1]
                let reff := GetFormFromMod "Oblivion.esm" $s
               let arKey[1] := reff
           else
               call zuERROR xxsSelf "Bad ref: " + asEntry[key] + "=" + asEntry[value]
           endif
       elseif eval (sv_Find "'" s) == 0
           let arKey[1] := s[1:(sv_length s) - 2]
       else
           let arKey[1] := ToNumber s
       endif

       let arr[arKey[0]] :=  arKey[1]

   loop
        
   SetFunctionValue arDesSerial 

   sv_destruct s ss
end

See Also[edit | edit source]