Attributes (OpScript)
=====================

Attribute Base Class
--------------------

.. lua:class:: Attribute()

   The abstract base class of all attributes.

   .. lua:method:: getType() -> int

      Returns a number representing the type of the attribute. This is useful
      for checking whether two attributes are of the same type.

   .. lua:method:: getHash() -> string

      Returns a string representation of the hash of the attribute.

   .. lua:method:: getHash64() -> int

      Returns a number representation of the hash of the attribute. Note that
      the value is a 64-bit hash value truncated to a 53-bit integer, which is
      guaranteed to be representable as a Lua number.

   .. lua:method:: getXML() -> string

      Returns a string containing a serialized XML representation of the
      attribute.

   .. lua:method:: getSize() -> int

      Returns the total memory in bytes that was allocated when the attribute
      was created.

Null Attributes
---------------

.. lua:class:: NullAttribute()

   A class representing a null value.

Data Attributes
---------------

.. lua:class:: DataAttribute(number|string|table|sequence data,\
      [number tupleSize=1])

   The abstract base class of attributes containing data, possibly at multiple
   samples in time. DataAttribute implements common, data-agnostic
   functionality, such as querying the number and orientation of values and
   time samples. This class cannot be instantiated directly. Instead, use one
   of:

   - :lua:class:`IntAttribute`
   - :lua:class:`FloatAttribute`
   - :lua:class:`DoubleAttribute`
   - :lua:class:`StringAttribute`

   *data* should be one of:

   - A single value, e.g. ``1``
   - A sequence of values, represented by one of:

      - a Lua table, e.g. ``{1, 2, 3}``
      - an OpScript :lua:class:`Array`, e.g. ``Array('int', {1, 2, 3})``
      - an OpScript :lua:class:`ArrayView`

   - An associative table that maps each time sample to a sequence of values,
     e.g. ``{[0.25] = {1, 2, 3}, [0.75] = {4, 5, 6}}``

   When time samples are not explicitly given, the attribute is created with
   a single sample at t=0.0.

   .. lua:method:: getNearestSample(float time) -> table<value>

      Returns the unmodified values of the sample nearest to a given time as
      value list.

      .. note:: :lua:func:`getNearestSample` returns a Lua table. Lua tables
         cannot contain more than 2^27 (134 million) values. Use
         :lua:func:`getSamples` to inspect and manipulate large attributes.

   .. lua:method:: getSamples() -> SampleAccessor

      Returns a read-only view into the samples of the attribute.

   .. lua:method:: getNumberOfTimeSamples() -> int

      Returns the number of time samples at which data is recorded in this
      attribute.

   .. lua:method:: getNumberOfTuples() -> int

      Returns the number of tuples in this attribute.

   .. lua:method:: getNumberOfValues() -> int

      Returns the total number of data values for this attribute. This will be
      equal to ``getNumberOfTuples() * getTupleSize()``.

   .. lua:method:: getSampleTime(int sampleIndex) -> float

      Returns a float value containing the time at a particular index for this
      attribute. If the index is not valid, 0.0 is returned.

   .. lua:method:: getTupleSize() -> int

      Return the number of data values per tuple for this attribute.

   .. lua:method:: getValue([value defaultValue, boolean throwOnError]) -> value

      Returns the first value from the time sample nearest 0.0. This is a
      convenience for the extremely common case of an attribute that stores a
      single sample of a single value at time 0.0.

      By default, throws exception if there are no time samples or no values
      available. However, if *defaultValue* is provided and *throwOnError* is
      ``false``, *defaultValue* will be returned.

.. lua:class:: IntAttribute(number|table data, [number tupleSize=1])

   A class representing a data attribute containing integers.

.. lua:class:: FloatAttribute(number|table data, [number tupleSize=1])

   A class representing a data attribute containing single-precision floats.

.. lua:class:: DoubleAttribute(number|table data, [number tupleSize=1])

   A class representing a data attribute containing double-precision floats.

.. lua:class:: StringAttribute(string|table data, [number tupleSize=1])

   A class representing a data attribute containing strings.

.. lua:class:: SampleAccessor

   SampleAccessor provides access to the sample buffers contained in a
   :lua:class:`DataAttribute`. Create one by calling the
   :lua:meth:`~DataAttribute:getSamples` method of any
   :lua:class:`DataAttribute`.

   Sample accessor objects support iterating over all time samples using the
   :lua:func:`ipairs` function. For example:

   .. code-block:: lua

      for i, sample in ipairs(myAttr:getSamples()) do
        ProcessSample(sample)
      end

   .. lua:method:: size() -> int

      Alias of :lua:func:`getNumberOfTimeSamples`. Note that you can also use
      the ``#`` operator.

      :returns: number of samples in the attribute

   .. lua:method:: empty() -> boolean

      Tests whether if the attribute has no time samples.

      :returns: *true* if the attribute has no time samples, *false* otherwise.

   .. lua:method:: front() -> Sample

      Returns the first sample. Raises an error if there are no time samples.

      :returns: the first sample

   .. lua:method:: back() -> Sample

      Returns the last sample. Raises an error if there are no time samples.

      :returns: the last sample

   .. lua:method:: getNumberOfTimeSamples() -> int

      Returns the number of samples in the attribute.

      :returns: the number of samples in the attribute

   .. lua:method:: getNumberOfValues() -> int

      Returns the number of values per sample.

      :returns: the number of values in each time sample.

   .. lua:method:: get(int sampleIndex) -> Sample

      Returns the sample at index *sampleIndex*.

      :param sampleIndex: the sample index to query
      :returns: the sample at index *sampleIndex*

   .. lua:method:: getNearestSample(float time) -> Sample

      Returns the sample closest to *time*. Returns an empty Sample object
      if the accessor contains no time samples.

      :param time: the time to query
      :returns: the sample closest to *time*

   .. lua:method:: getNearestSampleIndex(float time) -> int

      Returns the index of the sample closest to *time*. Returns ``0`` if the
      accessor contains no time samples.

      :param time: the time to query
      :returns: the index of the sample closest to *time*

   .. lua:method:: getSampleTimes() -> ArrayView<float>

      Returns a sequence of sample times.

      :returns: A read-only view into the sequence of sample times in the
         attribute.

.. lua:class:: Sample

   Sample objects represent a lightweight, read-only view into a particlar time
   sample of a :lua:class:`DataAttribute`.

   Like Lua tables, sample objects support iteration using the
   :lua:func:`ipairs` function, as well as taking the size with the ``#``
   operator. Unlike Lua tables, sample objects are indexed from *0*, not *1*.
   For example:

   .. code-block:: lua

      for i, sample in ipairs(myAttr:getSamples()) do
        for j, elem in ipairs(sample) do
          print(i, j, elem)
        end
      end

   This is equivalent to the following numeric for loop:

   .. code-block:: lua

      local samples = myAttr:getSamples()
      for i = 0, #samples - 1 do
        local sample = samples:get(i)
        for j = 0, #sample - 1 do
          print(i, j, sample:get(j))
        end
      end

   .. lua:method:: size() -> int

      Returns the number of elements in this sample. (Note that you can also
      use the ``#`` operator.)

   .. lua:method:: empty() -> boolean

      Checks whether the sample is empty.

   .. lua:method:: front() -> value

      Returns the first element. Raises an error if there are no values.

   .. lua:method:: back() -> value

      Returns the last element. Raises an error if there are no values.

   .. lua:method:: data() -> cdata<pointer>

      Returns a LuaJIT cdata pointer to the underlying data. This is an
      advanced feature -- be careful!

   .. lua:method:: get(int pos) -> value

      Accesses the element at the specified index. Raises an error if *pos* is
      not a valid index.

      :param pos: position of the element to return
      :returns: the element at the requested index

   .. lua:method:: getSampleTime() -> float

      Returns the sample's time.

      :returns: the time of the sample

   .. lua:method:: getSampleIndex() -> int

      Returns the index of the sample.

      :returns: the index of this sample in the underlying attribute

   .. lua:method:: getNumberOfValues() -> int

      Returns the number of values in the sample.

      :returns: the number of values in this sample

   .. lua:method:: toArray() -> Array

      Returns a mutable copy of this sample buffer.

      :returns: a mutable copy of this sample's data

Group Attributes
----------------

.. lua:class:: GroupAttribute([table children={}, boolean groupInherit=true])

   A class representing a group attribute, used for hierarchically
   encapsulating other attributes.

   *children*, if given, should be a table of key-value pairs. Each pair should
   be a 2-element table, where the key is a string giving the attribute name,
   and the value is an attribute.

   .. code-block:: lua

      local myGroup = GroupAttribute({{"a", IntAttribute(1)},
                                      {"b", IntAttribute(2)}}, true)

   *groupInherit*, if given, specifies whether this attribute should be
   inherited by descendant scene graph locations.

   :lua:class:`GroupBuilder` can be used to incrementally build a group
   attribute.

   .. lua:method:: getChildByIndex(int index) -> Attribute

      Returns a child attribute at given index. If index is out of range,
      ``nil`` is returned.

   .. lua:method:: getChildByName(string name) -> Attribute

      Looks up a child attribute by name and returns it. Returns ``nil`` if
      named child does not exist.

   .. lua:method:: getChildName(int index) -> string

      Returns the name of the child attribute at given index. If index is out of
      range, an empty string is returned.

   .. lua:method:: getGroupInherit() -> boolean

      Returns group inherit flag.

   .. lua:method:: getNumberOfChildren() -> int

      Returns the number of child attributes.

GroupBuilder
------------

A factory class for constructing GroupAttribute objects.

Typical usage involves creating a GroupBuilder, adding attributes to it with
the :lua:meth:`~GroupBuilder:set` method, and, when finished, retrieving a
newly constructed :lua:class:`GroupAttribute` using the GroupBuilder's
:lua:meth:`~GroupBuilder:build` method.

.. warning:: There is currently no way to inspect the contents of the builder,
   other than by calling :lua:meth:`~GroupBuilder:build` and inspecting the
   generated :lua:class:`GroupAttribute`. Note that by default
   :lua:meth:`~GroupBuilder:build` clears the contents of the builder; to
   override this behaviour pass
   ``GroupBuilder.BuilderBuildMode.BuildAndRetain`` to
   :lua:meth:`~GroupBuilder:build`.

As a convenience, GroupBuilder has support for creating arbitrarily nested
:lua:class:`GroupAttribute` structures by passing a dot-delimited string to
:lua:meth:`~GroupBuilder:set`, which is referred to as a "path". Note that this
implies that the ``.`` character is *not* a valid attribute name!

.. code-block:: lua

   local gb = GroupBuilder()
   gb:set("my.nested.attribute", IntAttribute(2))
   gb:set("myTopLevelAttribute", StringAttribute("taco"))
   gb:set("myOtherTopLevelAttribute", FloatAttribute(4.0))

   local groupAttribute = gb:build()

   -- Following the call to build(), gb is empty and groupAttribute has
   -- the following structure:
   --
   -- {
   --   "my": {
   --     "nested": {
   --       "attribute": IntAttribute(2)
   --      }
   --   },
   --   "myTopLevelAttribute": StringAttribute("taco"),
   --   "myOtherTopLevelAttribute": FloatAttribute(4.0f)
   -- }

.. lua:function:: GroupBuilder([GroupBuilder.BuilderMode mode=\
                               GroupBuilder.BuilderMode.Normal])

   Creates a new, empty :lua:class:`GroupBuilder` object.

   Possible values for *mode*:

   ``GroupBuilder.BuilderMode.Normal``
      The "normal" build mode, which allows the full suite of GroupBuilder
      functionality. This is the default.
   ``GroupBuilder.BuilderMode.Strict``
      An advanced option that enables a more restrictive but higher performance
      mode of operation.

      When working in this mode:

      - Callers must not pass dot-delimited paths to the
        :lua:meth:`~GroupBuilder:set` method.
      - Callers must not make multiple calls to :lua:meth:`~GroupBuilder:set`
        using the same path
      - Deletions are disallowed: the :lua:meth:`~GroupBuilder:del` method
        becomes a no-op.

.. lua:class:: GroupBuilder

   All methods except for :lua:meth:`~GroupBuilder:build` return a reference to
   self for method chaining.

   .. lua:method:: set(string path, Attribute attr, \
                       [boolean groupInherit=true])

      Sets the value for the attribute identified by the given path.

      If *path* refers to an existing attribute in the builder and the builder
      was created with ``GroupBuilder.BuilderMode.Normal``, the attribute is
      replaced. *attr* must be an Attribute object. If *path* is a
      dot-delimited path, *groupInherit* specifies the ``groupInherit`` flag
      for any new groups added by this call.

   .. lua:method:: setWithUniqueName(string path, Attribute attr, \
                                     [boolean groupInherit=true])

      Sets the value for an attribute identified using a unique name derived
      from the given path.

      If no attribute exists for the given path, this is equivalent to
      calling :lua:meth:`~set`. Otherwise, ``setWithUniqueName()`` chooses a new
      path by suffixing the given path with an integer. For example,
      calling ``setWithUniqueName("foo", ...)`` multiple times will produce
      paths ``foo``, ``foo1``, ``foo2``, and so on.

   .. lua:method:: update(GroupAttribute group)

      Updates the contents of the GroupBuilder with the attributes from the
      given GroupAttribute.

      Any new attributes with the same names as existing attributes replace the
      old ones. Existing attributes not matching new attributes are left
      intact. (This is analogous to the Python dictionary's ``update()``
      method.)

      If :lua:meth:`~GroupBuilder:setGroupInherit` has not been previously
      called, the GroupBuilder will also adopt on the incoming GroupAttribute's
      ``groupInherit``.

   .. lua:method:: deepUpdate(GroupAttribute group)

      Recursively updates the contents of the builder with attributes from the
      given GroupAttribute.

      Groups are traversed until set operations can be applied at the leaves
      which are **not** GroupAttributes themselves.

      If :lua:meth:`~GroupBuilder:setGroupInherit` has not been previously
      called, the GroupBuilder will also adopt on the incoming GroupAttribute's
      ``groupInherit``.

   .. lua:method:: del(string path)

      Deletes the attribute of the builder specified with the given *path*.

   .. lua:method:: reserve(int size)

      Reserves space for *size* attributes.

      This is an optimisation only. Calling ``reserve()`` before adding
      attributes will avoid having to reallocate internal data structures.

   .. lua:method:: sort()

      Sorts the top-level attributes by name.

      .. note:: ``sort()`` uses bytewise lexicographic ordering

   .. lua:method:: setGroupInherit(boolean groupInherit)

      Sets a special attribute on the builder that determines the value
      returned by :lua:meth:`~GroupAttribute:getGroupInherit` for the top-level
      :lua:class:`GroupAttribute` returned by :lua:meth:`~GroupBuilder:build`.

      This ``groupInherit`` flag is *sticky*, so once it's been set --
      either through an explicit call to
      :lua:meth:`~GroupBuilder:setGroupInherit`, or indirectly via a call to
      :lua:meth:`~GroupBuilder:update`/:lua:meth:`~GroupBuilder:deepUpdate()`
      -- further calls to ``setGroupInherit()`` will have no effect.

   .. lua:method:: build([BuilderBuildMode mode=\
         GroupBuilder.BuilderBuildMode.BuildAndFlush]) -> GroupAttribute

      Returns a newly created group attribute with the contents of the builder.

      Possible values for *mode*:

      ``GroupBuilder.BuilderBuildMode.BuildAndFlush``
        Specifies that the builder's contents are cleared following a call to
        ``build()``. This is the default.
      ``GroupBuilder.BuilderBuildMode.BuildAndRetain``
        Specifies that the builder's contents are retained following a call to
        ``build()``.

Utility Classes
-----------------

.. lua:class:: Array

   An OpScript **array** stores an ordered list of values of the same type.
   Elements are stored in a contiguous block of memory, which is expanded and
   contracted as needed. OpScript arrays are an advanced feature, and
   facilitate creating or manipulating large attributes.

   This interface is modelled on C++'s **std::vector** class, and differs from
   Lua's built-in table data structure in a number of ways:

   - OpScript arrays can only store values of the same type.
   - OpScript arrays are indexed from *0*, not *1*.
   - Attempting to access an invalid index raises a Lua error instead of
     returning ``nil``.
   - OpScript arrays have a theoretical maximum size of well above 2^32
     elements; Lua tables can address only 2^27 elements. (Note that at this
     time :lua:class:`DataAttribute` objects are themselves limited to 2^32
     elements.)
   - OpScript arrays cannot be indexed with the square bracket notation as
     tables can. Use ``myArray:get(myIndex)``, ``myArray:set(myIndex,
     myNewValue)``, not ``myTable[myIndex]`` and
     ``myTable[myIndex] = myNewValue``.

   .. code-block:: lua

      -- Creates an integer array of three elements
      local myIntArray = Array('int', {1, 2, 3})

      -- Creates a float array of three elements
      local myFloatArray = Array('float', {1, 2, 3})

      -- Creates a double array of three elements
      local myDoubleArray = Array('double', {1, 2, 3})

      -- Creates a string array of two elements
      local myStringArray = Array('string', {'hello', 'pony'})

   Like Lua tables, OpScript arrays support iteration using the
   :lua:func:`ipairs` function, as well as taking the size with the ``#``
   operator. For example:

   .. code-block:: lua

      for i, elem in ipairs(myArray) do
        print(i, elem)
      end

   This is equivalent to the following numeric for loop:

   .. code-block:: lua

      for i = 0, #myArray - 1 do
        print(i, myArray:get(i))
      end

   .. lua:function:: Array(ctype valueType)

      Creates an empty array.

      :param valueType: ctype (or ctype string) describing the element type

   .. lua:function:: Array(ctype valueType, sequence elems)

      Creates an array with a copy of *elems*.

      :param valueType: ctype (or ctype string) describing the element type
      :param elems: sequence of elements to initialize the array with

   .. lua:function:: Array(ctype valueType, number count, [value value])

      Creates an array with *count* copies of *value*.

      :param valueType: ctype (or ctype string) describing the element type
      :param count: size of the array
      :param value: value to initialize the array with

   .. lua:method:: size() -> int

      Returns the number of elements. (Note that you can also use the ``#``
      operator.)

   .. lua:method:: capacity() -> int

      Returns the number of elements that can be held in currently allocated
      storage.

   .. lua:method:: empty() -> boolean

      Checks whether the container is empty.

   .. lua:method:: front() -> value

      Returns the first element. Raises an error if the container is empty.

   .. lua:method:: back() -> value

      Returns the last element. Raises an error if the container is empty.

   .. lua:method:: data() -> cdata<pointer>

      Returns a LuaJIT cdata pointer to the underlying data. This is an
      advanced feature -- be careful!

   .. lua:method:: get(int pos) -> value

      Accesses the element at the index *pos*. Raise an error if *pos* is not a
      valid index.

      :param pos: position of the element to return
      :returns: the element at the requested index

   .. lua:method:: set(int pos, value value)

      Assigns a value to an index *pos*. Raises an error if *pos* is not a
      valid index.

      :param pos: position of the element to assign
      :param value: the element to assign

   .. lua:method:: clear()

      Clears the contents.

   .. lua:method:: shrinkToFit()

      Reduces memory usage by freeing unused memory.

   .. lua:method:: reserve(int newCapacity)

      Reserves storage. If *newCapacity* is greater than the current
      *capacity*, new storage is allocated, otherwise the method does nothing.

      :param newCapacity: amount of storage to reserve

   .. lua:method:: resize(int count, [value value])

      Changes the number of elements stored. If *count* is greater than the
      current size, additional elements are initialized with copies of *value*.

      :param count: count the new size of the container
      :param value: the value to initialize new elements with

   .. lua:method:: assign(sequence elems)

      Assigns a sequence of elements -- for example, a Lua table or another
      array -- to the array.

      :param elems: a sequence of elements to assign to the container

   .. lua:method:: assign(int count, value value)

      Assigns *count* copies of *value* to the array.

      :param count: the new size of the container
      :param value: the value to initialize elements of the container with

   .. lua:method:: pushBack(value value)

      Appends *value* to the end of the array.

      :param value: the value of the element to append

   .. lua:method:: popBack() -> value

      Removes the last element. Raises an error if the container is empty.

      :returns: the removed element

   .. lua:method:: insert(int pos, value value)

      Inserts an element at index *pos*. Raises an error if *pos* is less than
      zero or greater than the number of elements in the container.

      :param pos: position before which the content will be inserted
      :param value: element value to insert

   .. lua:method:: insert(int pos, sequence elems)

      Inserts elements from *sequence* at index *pos*. Raises an error if
      *pos* is less than zero or greater than the number of elements in the
      container.

      :param pos: position before which the content will be inserted
      :param elems: the elements to insert

   .. lua:method:: insert(int pos, int count, value value)

      Inserts *count* copies of *value* at index *pos*. Raises an error if
      *pos* is less than zero or greater than the number of elements in the
      container.

      :param pos: position before which the content will be inserted
      :param count: the number of values to insert
      :param value: element value to insert

   .. lua:method:: erase(int pos)

      Erases the element at index *pos*. Raise an error if *pos* is not a valid
      index.

      :param pos: position of the element to erase

   .. lua:method:: erase(int first, int last)

      Erases elements in the half-open range ``[first last)``. Raises an error
      this does not denote a valid half-open range.

      :param first: position of the first element to erase
      :param last: position of the first element greater than or equal to
         *first* that should be preserved

.. lua:class:: ArrayView

   A class representing a lightweight, read-only view into a typed data buffer.

   ArrayView's interface differs from Lua's built-in table data structure in a
   number of ways:

   - Array view objects are indexed from *0*, not *1*.
   - Attempting to access an invalid index raises a Lua error instead of
     returning ``nil``.
   - Array view objects cannot be indexed with the square bracket notation as
     tables can. Use ``myView:get(myIndex)``, not ``myTable[myIndex]``.

   Like Lua tables, array view objects support iteration using the
   :lua:func:`ipairs` function, as well as taking the size with the ``#``
   operator. For example:

   .. code-block:: lua

      for i, elem in ipairs(myView) do
        print(i, elem)
      end

   This is equivalent to the following numeric for loop:

   .. code-block:: lua

      for i = 0, #myView - 1 do
        print(i, myView:get(i))
      end

   .. lua:function:: ArrayView(ctype valueType, cdata<pointer> data, \
         int count, [object owner])

      Creates an ArrayView. Instantiating an ArrayView directly is an advanced
      feature not required in typical OpScript usage.

      :param valueType: ctype (or ctype string) describing the element type
      :param data: LuaJIT cdata pointer to a data buffer
      :param count: number of values in the buffer
      :param owner: object who owns the data being pointed at. ArrayView will
         ensure this object is not garbage collected until the view object is
         itself garbage collected.

   .. lua:method:: size() -> int

      Returns the number of elements. (Note that you can also use the ``#``
      operator.)

   .. lua:method:: empty() -> boolean

      Checks whether the container is empty.

   .. lua:method:: front() -> value

      Returns the first element. Raises an error if the container is empty.

   .. lua:method:: back() -> value

      Returns the last element. Raises an error if the container is empty.

   .. lua:method:: data() -> cdata<pointer>

      Returns a LuaJIT cdata pointer to the underlying data. This is an
      advanced feature -- be careful!

   .. lua:method:: get(int pos) -> value

      Accesses the element at the specified index. Raise an error if *pos* is
      not a valid index.

      :param pos: position of the element to return
      :returns: the element at the requested index


Utility Functions
-----------------

.. lua:module:: Attribute

.. lua:function:: DelimiterEncode(string token) -> string

   Utility function that encodes (escapes) period (``.``) and slash (``/``)
   characters in *token* and returns the result. This is useful when adding
   :lua:class:`GroupAttribute` children with periods and slashes in their
   names. On retrieval these names can be decoded with
   :lua:func:`DelimiterDecode`.

   Performs the following substitutions:

   - FULL STOP (``0x2E``) -> DEGREE SIGN (``0xB0``)
   - SLASH (``0x2F``) -> PLUS-MINUS SIGN (``0xB1``)

.. lua:function:: DelimiterDecode(string token) -> string

   Utility function that decodes escaped period (``.``) and slash (``/``)
   characters in *token* and returns the result. This is useful when retrieving
   :lua:class:`GroupAttribute` children whose names were previously encoded via
   :lua:func:`DelimiterEncode`.

   Performs the following substitutions:

   - DEGREE SIGN (``0xB0``) -> FULL STOP (``0x2E``)
   - PLUS-MINUS SIGN (``0xB1``) -> SLASH (``0x2F``)

.. lua:function:: GetTotalSize() -> int

   Returns the total memory currently allocated by the FnAttribute library.

.. lua:function:: GetIntValue(object obj, number defaultValue) -> int

   If *obj* is an :lua:class:`IntAttribute`, this function returns its first
   value. Otherwise it returns *defaultValue*.

.. lua:function:: GetFloatValue(object obj, float defaultValue) -> float

   If *obj* is a :lua:class:`FloatAttribute`, this function returns its first
   value. Otherwise it returns *defaultValue*.

.. lua:function:: GetDoubleValue(object obj, float defaultValue) -> float

   If *obj* is a :lua:class:`DoubleAttribute`, this function returns its first
   value. Otherwise it returns *defaultValue*.

.. lua:function:: GetStringValue(object obj, string defaultValue) -> string

   If *obj* is a :lua:class:`StringAttribute`, this function returns its first
   value. Otherwise it returns *defaultValue*.

.. lua:function:: IsAttribute(object obj) -> boolean

   Returns ``true`` if *obj* is an :lua:class:`Attribute`, ``false``
   otherwise.

.. lua:function:: IsNull(object obj) -> boolean

   Returns ``true`` if *obj* is an :lua:class:`NullAttribute`, ``false``
   otherwise.

.. lua:function:: IsInt(object obj) -> boolean

   Returns ``true`` if *obj* is an :lua:class:`IntAttribute`, ``false``
   otherwise.

.. lua:function:: IsFloat(object obj) -> boolean

   Returns ``true`` if *obj* is an :lua:class:`FloatAttribute`, ``false``
   otherwise.

.. lua:function:: IsDouble(object obj) -> boolean

   Returns ``true`` if *obj* is an :lua:class:`DoubleAttribute`, ``false``
   otherwise.

.. lua:function:: IsString(object obj) -> boolean

   Returns ``true`` if *obj* is an :lua:class:`StringAttribute`, ``false``
   otherwise.

.. lua:function:: IsGroup(object obj) -> boolean

   Returns ``true`` if *obj* is an :lua:class:`GroupAttribute`, ``false``
   otherwise.