obj_save

obj_save saves an object as an XML file or as an binary file on the hard drive or as a string.

ret = obj_save(obj, ssFilename)
ret = obj_save(obj, ssFilename, ssFormat)
ssXMLString = obj_save(obj, "")

Return Value

If ssFilename is a complete file name, ret is not equal 0, if the function was successful and 0 if an error occurred. If the file name has the extension .uso (for Uni Script Object) the file will be saved in a binary format.

ssXMLString:

If ssFilename is an empty string (""), the return value is a string with the XML code of the obj object or if ssFormat is set to "binary", "b" or "uncompressed-binary" or "u" the object is returned in a binary format.

Parameters

obj

obj is the object created with obj_create.

ssFilename

ssFilename is the complete file name or an empty string. See ret

ssFormat

ssFormat is a format string to specify the number format (see printf) (The default value is "%.20g"), or the string "binary" or "b", "uncompressed-binary" or "u" to save the file in a binary format.

Example

obj = obj_create()
obj[1] = 123
obj.a = "Hello"
obj.c = obj_create()
obj.c.d = 456
obj.save("d:\\test.xml")

creates the following XML file:

<?xml version='1.0' encoding='utf-8'?>
<obj ID='1'>
    <number ikey='1'>123</number>
    <string key='a'>Hello</string>
    <obj ID='2' key='c'>
        <number key='d'>456</number>
    </obj>
</obj>

An empty string saves the object in an xml string:

s = obj.save("")

"binary" creates a binary format:

s = obj.save("", "binary")
mem_dump(s)

Comment

Notes

  • Saving the data in a binary fomat is approx 50 times faster than in an xml format.
  • Saving the data as string is appropriate for objects smaller than some MB. Bigger objects should be saved in the binary format.

XML-Scheme

RelaxNG scheme for the XML file (see also http://relaxng.org/compact-tutorial-20030326.html):

obj = element obj { obj_attlist, (obj_inner | simple)* }
obj_attlist = attribute id { xsd:positiveInteger }?

simple =
  number
  | \string
  | complex
  | number-matrix
  | string-matrix
  | complex-matrix
  | variant-matrix

obj_inner = element obj { obj_inner_attlist, simple* }
obj_inner_attlist =
  key_or_ikey,
  attribute id { xsd:positiveInteger }?,
  attribute ref { xsd:positiveInteger }?
#
number = element number { key_or_ikey, xsd:double }
\string = element string { string_attlist, text }
string_attlist =
  key_or_ikey,
  attribute encoding { xsd:string "base64" }?
complex = element complex { key_or_ikey, cpx }
#
mat_number = element number { xsd:double }
mat_string = element string { mat_string_attlist, text }
mat_string_attlist = attribute encoding { xsd:string "base64" }?
mat_complex = element complex { cpx }
#
number-matrix = element number-matrix { matrix_attlist, mat_number+ }
string-matrix = element string-matrix { matrix_attlist, mat_string+ }
complex-matrix = element complex-matrix { matrix_attlist, mat_complex+ }
variant-matrix =
  element variant-matrix {
    matrix_attlist, (mat_number | mat_string | mat_complex)+
  }
cpx = xsd:string { pattern = "[\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?[\-+][0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?i" }
key_or_ikey =
  attribute key { text }
  | attribute ikey { xsd:double }
row_cols =
  attribute rows { xsd:positiveInteger },
  attribute cols { xsd:positiveInteger }
matrix_attlist = key_or_ikey, row_cols

Binary format

header: "USO" version-number
object: 'o' len ikey id-or-ref
object: 'p' len key id-or-ref
endofobj: ')'

double: 'n' ikey data
double: 'm' key data
string: 's' ikey string
string: 't' key string
complex: 'c' ikey cdata
complex: 'd' key cdata

matrix: 'N' len ikey shape data
matrix: 'M' len key shape data
smatrix: 'S' len ikey shape string
smatrix: 'T' len key shape string
cmatrix: 'C' len ikey shape cdata
cmatrix: 'D' len key shape cdata
vmatrix: 'V' len ikey shape vdata
vmatrix: 'W' len key shape vdata

All values are saved in little-endian byte order (LEBO).

The header (4 bytes) is followed by the object ‘o’ with the ID=1 and the key ikey=0.0. The object is followed by an abitray number of objects and other data elements. Each object is terminated with an endofobj: ‘)’.

version-number byte, version number is 1.
len Each matrix and object tag is followed by the element length. The length is a 64-Bit integer.
ikey Number key (double - 8 Bytes).
key keylen (int32) in bytes, followed by any number of UTF-16 characters. All UNICODE characters can be used for keys except null characters.
id_or_ref (int32), ID of the object (1, 2, …) or, if id_or_ref is negative, reference of an object.
shape nrows (int32) ncols (int32). Number of rows and columns of a matrix The matrix elements are saved column wise: a[1;1], a[2;1], …
string len (int32) in bytes, followed by UTF-16 characters or bytes (also 0-bytes).
data Matrix with double numbers (double - 8 Bytes). If the format is not "uncompressed-binary", the data is saved as a block with LZ4 compression (https://code.google.com/p/lz4/). If len is equal nrows*ncols*8, the data is uncompressed. In this version, only matrices with double numbers are compressed. String matrices, complex matrices, variant matrices and objects are not compressed.
cdata Matrix with complex elements (two double values: real, imag).
vdata Variant matrix. Elements can be numbers, complex numbers, strings or Objects. The value starts with the byte ‘n’, ‘c’, ‘s’ or ‘o’.

Circular Reference

The function can also save nested objects with references, e.g.

obj = obj_create()
obj.val = 123
obj.next = obj_create()
obj.next.val = 456
obj.next.next = obj
obj.save("d:\\test1.xml")

creates the follow XML file (note attributes id and ref):

<?xml version='1.0' encoding='utf-8'?>
<obj id='1'>
    <obj id='2' key='next'>
        <obj key='next' ref='1'/>
        <number key='val'>456</number>
    </obj>
    <number key='val'>123</number>
</obj>

History

Version Description
R2014.3 Objects can be saved in a binary format.
5.10.0 An empty string can be used as a file name.
5.0.0 Unicode changes.
4.1.0 New.

id-699932