Переглянути джерело

add c2rst tool to generate documentation from header files

Julius Pfrommer 8 роки тому
батько
коміт
26cd7ec423
7 змінених файлів з 441 додано та 941 видалено
  1. 1 9
      CMakeLists.txt
  2. 23 0
      doc/CMakeLists.txt
  3. 0 685
      doc/datatypes.rst
  4. 1 1
      doc/index.rst
  5. 321 235
      include/ua_types.h
  6. 81 0
      tools/c2rst.py
  7. 14 11
      tools/travis_push_doc.sh

+ 1 - 9
CMakeLists.txt

@@ -510,14 +510,6 @@ if(UA_BUILD_EXAMPLES)
 	endif()
 endif()
 
-# build documentation
 if(UA_BUILD_DOCUMENTATION)
-    find_package(Sphinx REQUIRED)
-    add_custom_target(doc_latex ${SPHINX_EXECUTABLE}
-      -b latex -c "${PROJECT_SOURCE_DIR}/doc" "${PROJECT_SOURCE_DIR}/doc" "${PROJECT_BINARY_DIR}/doc_latex"
-      COMMENT "Building LaTeX sources for documentation with Sphinx")
-    add_custom_target(doc ${SPHINX_EXECUTABLE}
-      -b html -c "${PROJECT_SOURCE_DIR}/doc" "${PROJECT_SOURCE_DIR}/doc" "${PROJECT_BINARY_DIR}/doc"
-      COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/doc/open62541_html.png" "${PROJECT_BINARY_DIR}/doc/_static/"
-      COMMENT "Building HTML documentation with Sphinx")
+    add_subdirectory(doc)
 endif()

+ 23 - 0
doc/CMakeLists.txt

@@ -0,0 +1,23 @@
+find_package(Sphinx REQUIRED)
+
+file(COPY ${PROJECT_SOURCE_DIR}/doc DESTINATION ${PROJECT_BINARY_DIR})
+
+function(generate_rst in out)
+  add_custom_command(OUTPUT ${out}
+                     DEPENDS ${PROJECT_SOURCE_DIR}/tools/c2rst.py ${in}
+                     PRE_BUILD
+                     COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/c2rst.py ${in} ${out})
+endfunction()
+
+generate_rst(${PROJECT_SOURCE_DIR}/include/ua_types.h ${PROJECT_BINARY_DIR}/doc/types.rst)
+
+add_custom_target(doc_latex ${SPHINX_EXECUTABLE}
+  -b latex -c "${PROJECT_BINARY_DIR}/doc" "${PROJECT_BINARY_DIR}/doc" "${PROJECT_BINARY_DIR}/doc_latex"
+  DEPENDS ${PROJECT_BINARY_DIR}/doc/types.rst
+  COMMENT "Building LaTeX sources for documentation with Sphinx")
+add_custom_target(doc ${SPHINX_EXECUTABLE}
+  -b html -c "${PROJECT_BINARY_DIR}/doc" "${PROJECT_BINARY_DIR}/doc" "${PROJECT_BINARY_DIR}/doc_html"
+  COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_BINARY_DIR}/doc/open62541_html.png" "${PROJECT_BINARY_DIR}/doc_html/_static/"
+  DEPENDS ${PROJECT_BINARY_DIR}/doc/types.rst
+  COMMENT "Building HTML documentation with Sphinx")
+

+ 0 - 685
doc/datatypes.rst

@@ -1,685 +0,0 @@
-Data Types
-==========
-
-Introduction
-------------
-
-In open62541, all data types share the same basic API for creation, copying and
-deletion. The following functions are present for all data types ``T``.
-
-``void T_init(T *ptr)``
-  Initialize the data type. This is synonymous with zeroing out the memory, i.e. *memset(dataptr, 0, sizeof(T))*.
-``T* T_new()``
-  Allocate and return the memory for the data type. The memory is already initialized.
-``UA_StatusCode T_copy(const T *src, T *dst)``
-  Copy the content of the data type. Returns *UA_STATUSCODE_GOOD* if it succeeded.
-``void T_deleteMembers(T *ptr)``
-  Delete the dynamically allocated content of the data type, but not the data type itself.
-``void T_delete(T *ptr)``
-  Delete the content of the data type and the memory for the data type itself.
-
-The builtin data types
-----------------------
-
-OPC UA defines 25 builtin data types. All other data types are combinations of
-the 25 builtin data types.
-
-UA_Boolean
-^^^^^^^^^^
-
-A two-state logical value (true or false).
-
-.. code-block:: c
-
-  typedef bool UA_Boolean;
-  #define UA_TRUE true
-  #define UA_FALSE false
-
-UA_SByte
-^^^^^^^^
-
-An integer value between -128 and 127.
-
-.. code-block:: c
-
-  typedef int8_t UA_SByte;
-
-UA_Byte
-^^^^^^^
-
-An integer value between 0 and 256.
-
-.. code-block:: c
-
-  typedef uint8_t UA_Byte;
-
-UA_Int16
-^^^^^^^^
-
-An integer value between -32,768 and 32,767.
-
-.. code-block:: c
-
-  typedef int16_t UA_Int16;
-
-UA_UInt16
-^^^^^^^^^
-
-An integer value between 0 and 65,535.
-
-.. code-block:: c
-
-  typedef uint16_t UA_UInt16;
-
-UA_Int32
-^^^^^^^^
-
-An integer value between -2,147,483,648 and 2,147,483,647.
-
-.. code-block:: c
-
-  typedef int32_t UA_Int32;
-
-UA_UInt32
-^^^^^^^^^
-
-An integer value between 0 and 4,294,967,295.
-
-.. code-block:: c
-
-  typedef uint32_t UA_UInt32;
-
-The following functions and definitions are used with UA_UInt32.
-
-.. code-block:: c
-
-  /* do not use for cryptographic entropy */
-  UA_UInt32 UA_UInt32_random(void);
-
-UA_Int64
-^^^^^^^^
-
-An integer value between -10,223,372,036,854,775,808 and 9,223,372,036,854,775,807.
-
-.. code-block:: c
-
-  typedef int64_t UA_Int64;
-
-UA_UInt64
-^^^^^^^^^
-
-An integer value between 0 and 18,446,744,073,709,551,615.
-
-.. code-block:: c
-
-  typedef uint64_t UA_UInt64;
-
-UA_Float
-^^^^^^^^
-
-An IEEE single precision (32 bit) floating point value.
-
-.. code-block:: c
-
-  typedef float UA_Float;
-
-UA_Double
-^^^^^^^^^
-
-An IEEE double precision (64 bit) floating point value.
-
-.. code-block:: c
-
-  typedef double UA_Double;
-
-UA_DateTime
-^^^^^^^^^^^
-
-An instance in time. A DateTime value is encoded as a 64-bit signed integer
-which represents the number of 100 nanosecond intervals since January 1, 1601
-(UTC).
-
-.. code-block:: c
-
-  typedef UA_Int64 UA_DateTime;
-
-The following functions and definitions are used with UA_DateTime.
-
-.. code-block:: c
-
-  UA_DateTime UA_DateTime_now(void);
-
-  typedef struct UA_DateTimeStruct {
-      UA_UInt16 nanoSec;
-      UA_UInt16 microSec;
-      UA_UInt16 milliSec;
-      UA_UInt16 sec;
-      UA_UInt16 min;
-      UA_UInt16 hour;
-      UA_UInt16 day;
-      UA_UInt16 month;
-      UA_UInt16 year;
-  } UA_DateTimeStruct;
-
-  UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime time);
-
-  UA_String UA_DateTime_toString(UA_DateTime time);
-
-UA_Guid
-^^^^^^^
-
-A 16 byte value that can be used as a globally unique identifier.
-
-.. code-block:: c
-
-  typedef struct {
-      UA_UInt32 data1;
-      UA_UInt16 data2;
-      UA_UInt16 data3;
-      UA_Byte   data4[8];
-  } UA_Guid;
-
-The following functions and definitions are used with UA_Guid.
-
-.. code-block:: c
-
-  UA_Boolean UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2);
-
-  /* do not use for cryptographic entropy */
-  UA_Guid UA_Guid_random();
-
-UA_String
-^^^^^^^^^
-
-A sequence of Unicode characters. See also the section :ref:`array-handling` for
-the usage of arrays in open62541.
-
-.. code-block:: c
-
-  typedef struct {
-      size_t length; // The length of the string
-      UA_Byte *data; // The string's content (not null-terminated)
-  } UA_String;
-
-The following functions and definitions are used with UA_String.
-
-.. code-block:: c
-
-  extern const UA_String UA_STRING_NULL;
-
-  UA_String UA_STRING(char *chars);
-
-  #define UA_STRING_ALLOC(CHARS) UA_String_fromChars(CHARS)
-    
-  /** Copies the content on the heap. Returns a null-string when alloc fails */
-  UA_String UA_String_fromChars(char const src[]);
-
-  UA_Boolean UA_String_equal(const UA_String *s1, const UA_String *s2);
-
-Here's a small example for the usage of UA_String.
-
-.. code-block:: c
-
-  /* The definition of UA_String copied from ua_types.h */ 
-  typedef struct {
-      size_t length; ///< The length of the string
-      UA_Byte *data; ///< The string's content (not null-terminated)
-  } UA_String;
-
-  UA_String s1 = UA_STRING("test1");       /* s1 points to the statically allocated string buffer */
-  UA_String_init(&s1);                     /* Reset s1 (no memleak due to the statically allocated buffer) */
-  
-  UA_String s2 = UA_STRING_ALLOC("test2"); /* s2 points to a new copy of the string buffer (with malloc) */
-  UA_String_deleteMembers(&s2);            /* Free the content of s2, but not s2 itself */
-  
-  UA_String *s3 = UA_String_new();         /* The string s3 is malloced and initialized */
-  *s3 = UA_STRING_ALLOC("test3");          /* s3 points to a new copy of the string buffer */
-  
-  UA_String s4;
-  UA_copy(s3, &s4);                        /* Copy the content of s3 to s4 */
-  
-  UA_String_delete(s3);                    /* Free the string buffer and the string itself */
-  UA_String_deleteMembers(&s4);            /* Again, delete only the string buffer */
-
-UA_ByteString
-^^^^^^^^^^^^^
-
-A sequence of octets.
-
-.. code-block:: c
-
-  typedef UA_String UA_ByteString;
-
-UA_XmlEelement
-^^^^^^^^^^^^^^
-
-An XML element.
-
-.. code-block:: c
-
-  typedef UA_String UA_XmlElement;
-
-UA_NodeId
-^^^^^^^^^
-
-An identifier for a node in the address space of an OPC UA Server.
-
-.. code-block:: c
-
-  enum UA_NodeIdType {
-      UA_NODEIDTYPE_NUMERIC    = 0, // On the wire, this can be 0, 1 or 2 (shortened numeric nodeids)
-      UA_NODEIDTYPE_STRING     = 3,
-      UA_NODEIDTYPE_GUID       = 4,
-      UA_NODEIDTYPE_BYTESTRING = 5
-  };
-
-  typedef struct {
-      UA_UInt16 namespaceIndex;
-      enum UA_NodeIdType identifierType;
-      union {
-          UA_UInt32     numeric;
-          UA_String     string;
-          UA_Guid       guid;
-          UA_ByteString byteString;
-      } identifier;
-  } UA_NodeId;
-
-The following functions and definitions are used with UA_NodeId.
-
-.. code-block:: c
-
-  UA_Boolean UA_NodeId_isNull(const UA_NodeId *p);
-
-  UA_Boolean UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2);
-
-  extern const UA_NodeId UA_NODEID_NULL;
-
-  UA_NodeId UA_NODEID_NUMERIC(UA_UInt16 nsIndex, UA_Int32 identifier);
-
-  UA_NodeId UA_NODEID_STRING(UA_UInt16 nsIndex, char *chars) {
-
-  UA_NodeId UA_NODEID_STRING_ALLOC(UA_UInt16 nsIndex, const char *chars);
-
-  UA_NodeId UA_NODEID_GUID(UA_UInt16 nsIndex, UA_Guid guid);
-
-  UA_NodeId UA_NODEID_BYTESTRING(UA_UInt16 nsIndex, char *chars);
-
-  UA_NodeId UA_NODEID_BYTESTRING_ALLOC(UA_UInt16 nsIndex, const char *chars);
-
-UA_ExpandedNodeId
-^^^^^^^^^^^^^^^^^
-
-A NodeId that allows the namespace URI to be specified instead of an index.
-
-.. code-block:: c
-
-  typedef struct {
-      UA_NodeId nodeId;
-      UA_String namespaceUri;
-      UA_UInt32 serverIndex;
-  } UA_ExpandedNodeId;
-
-The following functions and definitions are used with UA_ExpandedNodeId.
-
-.. code-block:: c
-
-  UA_ExpandedNodeId UA_EXPANDEDNODEID_NUMERIC(UA_UInt16 nsIndex, UA_Int32 identifier);
-
-  UA_ExpandedNodeId UA_EXPANDEDNODEID_STRING(UA_UInt16 nsIndex, char *chars);
-
-  UA_ExpandedNodeId UA_EXPANDEDNODEID_STRING_ALLOC(UA_UInt16 nsIndex, const char *chars);
-
-  UA_ExpandedNodeId UA_EXPANDEDNODEID_STRING_GUID(UA_UInt16 nsIndex, UA_Guid guid);
-
-  UA_ExpandedNodeId UA_EXPANDEDNODEID_BYTESTRING(UA_UInt16 nsIndex, char *chars);
-
-  UA_ExpandedNodeId UA_EXPANDEDNODEID_BYTESTRING_ALLOC(UA_UInt16 nsIndex, const char *chars);
-
-UA_QualifiedName
-^^^^^^^^^^^^^^^^
-
-A name qualified by a namespace.
-
-.. code-block:: c
-
-  typedef struct {
-      UA_UInt16 namespaceIndex;
-      UA_String name;
-  } UA_QualifiedName;
-
-The following functions and definitions are used with UA_QualifiedName.
-
-.. code-block:: c
-
-  UA_QualifiedName UA_QUALIFIEDNAME(UA_UInt16 nsIndex, char *chars);
-
-  UA_QualifiedName UA_QUALIFIEDNAME_ALLOC(UA_UInt16 nsIndex, const char *chars);
-
-UA_LocalizedText
-^^^^^^^^^^^^^^^^
-
-Human readable text with an optional locale identifier.
-
-.. code-block:: c
-
-  typedef struct {
-      UA_String locale;
-      UA_String text;
-  } UA_LocalizedText;
-                
-The following functions and definitions are used with UA_LocalizedText.
-
-.. code-block:: c
-
-  UA_LocalizedText UA_LOCALIZEDTEXT(char *locale, char *text);
-
-  UA_LocalizedText UA_LOCALIZEDTEXT_ALLOC(const char *locale, const char *text);
-
-UA_ExtensionObject
-^^^^^^^^^^^^^^^^^^
-
-A structure that contains an application specific data type that may not be
-recognized by the receiver.
-
-.. code-block:: c
-
-  typedef struct {
-      enum {
-          UA_EXTENSIONOBJECT_ENCODED_NOBODY     = 0,
-          UA_EXTENSIONOBJECT_ENCODED_BYTESTRING = 1,
-          UA_EXTENSIONOBJECT_ENCODED_XML        = 2,
-          UA_EXTENSIONOBJECT_DECODED            = 3, ///< There is a pointer to the decoded data
-          UA_EXTENSIONOBJECT_DECODED_NODELETE   = 4  ///< Don't delete the decoded data at the lifecycle end
-      } encoding;
-      union {
-          struct {
-              UA_NodeId typeId; ///< The nodeid of the datatype
-              UA_ByteString body; ///< The bytestring of the encoded data
-          } encoded;
-          struct {
-              const UA_DataType *type;
-              void *data;
-          } decoded;
-      } content;
-  } UA_ExtensionObject;
-
-UA_Variant
-^^^^^^^^^^
-
-Stores (arrays of) any data type. Please see section :ref:`generic-handling` for
-the usage of UA_DataType. The semantics of the arrayLength field is explained in
-section :ref:`array-handling`.
-
-.. code-block:: c
-
-  typedef struct {
-      const UA_DataType *type; // The data type description
-      enum {
-          UA_VARIANT_DATA,          /* The data has the same lifecycle as the variant */
-          UA_VARIANT_DATA_NODELETE, /* The data is "borrowed" by the variant and shall not be
-                                       deleted at the end of the variant's lifecycle. */
-      } storageType;
-      size_t arrayLength;  // The number of elements in the data array
-      void *data; // Points to the scalar or array data
-      size_t arrayDimensionsSize; // The number of dimensions the data-array has
-      UA_UInt32 *arrayDimensions; // The length of each dimension of the data-array
-  } UA_Variant;
-
-  /* NumericRanges are used to indicate subsets of a (multidimensional) variant
-  * array. NumericRange has no official type structure in the standard. On the
-  * wire, it only exists as an encoded string, such as "1:2,0:3,5". The colon
-  * separates min/max index and the comma separates dimensions. A single value
-  * indicates a range with a single element (min==max). */
-  typedef struct {
-      size_t dimensionsSize;
-      struct UA_NumericRangeDimension {
-          UA_UInt32 min;
-          UA_UInt32 max;
-      } *dimensions;
-  } UA_NumericRange;
-
-
-The following functions and definitions are used with UA_Variant.
-
-.. code-block:: c
-
-  /**
-   * Returns true if the variant contains a scalar value. Note that empty
-   * variants contain an array of length -1 (undefined).
-   *
-   * @param v The variant
-   * @return Does the variant contain a scalar value.
-   */
-  UA_Boolean UA_Variant_isScalar(const UA_Variant *v);
-
-  /**
-   * Set the variant to a scalar value that already resides in memory. The value
-   * takes on the lifecycle of the variant and is deleted with it.
-   *
-   * @param v The variant
-   * @param p A pointer to the value data
-   * @param type The datatype of the value in question
-   */
-  UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p, const UA_DataType *type);
-
-  /**
-   * Set the variant to a scalar value that is copied from an existing variable.
-   *
-   * @param v The variant
-   * @param p A pointer to the value data
-   * @param type The datatype of the value
-   * @return Indicates whether the operation succeeded or returns an error code
-   */
-  UA_StatusCode UA_Variant_setScalarCopy(UA_Variant *v, const void *p, const UA_DataType *type);
-
-  /**
-   * Set the variant to an array that already resides in memory. The array takes
-   * on the lifecycle of the variant and is deleted with it.
-   *
-   * @param v The variant
-   * @param array A pointer to the array data
-   * @param arraySize The size of the array
-   * @param type The datatype of the array
-   */
-  void UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
-                           size_t arraySize, const UA_DataType *type);
-
-  /**
-   * Set the variant to an array that is copied from an existing array.
-   *
-   * @param v The variant
-   * @param array A pointer to the array data
-   * @param arraySize The size of the array
-   * @param type The datatype of the array
-   * @return Indicates whether the operation succeeded or returns an error code
-   */
-  UA_StatusCode UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
-                                        size_t arraySize, const UA_DataType *type);
-
-  /**
-   * Copy the variant, but use only a subset of the (multidimensional) array
-   * into a variant. Returns an error code if the variant is not an array or if
-   * the indicated range does not fit.
-   *
-   * @param src The source variant
-   * @param dst The target variant
-   * @param range The range of the copied data
-   * @return Returns UA_STATUSCODE_GOOD or an error code
-   */
-  UA_StatusCode UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
-                                     const UA_NumericRange range);
-
-  /**
-   * Insert a range of data into an existing variant. The data array can't be
-   * reused afterwards if it contains types without a fixed size (e.g. strings)
-   * since the members are moved into the variant and take on its lifecycle.
-   *
-   * @param v The variant
-   * @param dataArray The data array. The type must match the variant
-   * @param dataArraySize The length of the data array. This is checked to match the range size.
-   * @param range The range of where the new data is inserted
-   * @return Returns UA_STATUSCODE_GOOD or an error code
-   */
-  UA_StatusCode UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array,
-                                    size_t arraySize, const UA_NumericRange range);
-
-  /**
-   * Deep-copy a range of data into an existing variant.
-   *
-   * @param v The variant
-   * @param dataArray The data array. The type must match the variant
-   * @param dataArraySize The length of the data array. This is checked to match the range size.
-   * @param range The range of where the new data is inserted
-   * @return Returns UA_STATUSCODE_GOOD or an error code
-   */
-  UA_StatusCode UA_Variant_setRangeCopy(UA_Variant *v, const void *array,
-                                        size_t arraySize, const UA_NumericRange range);
-
-UA_DataValue
-^^^^^^^^^^^^
-
-A data value with an associated status code and timestamps.
-
-.. code-block:: c
-   
-  typedef struct {
-      UA_Boolean    hasValue             : 1;
-      UA_Boolean    hasStatus            : 1;
-      UA_Boolean    hasSourceTimestamp   : 1;
-      UA_Boolean    hasServerTimestamp   : 1;
-      UA_Boolean    hasSourcePicoseconds : 1;
-      UA_Boolean    hasServerPicoseconds : 1;
-      UA_Variant    value;
-      UA_StatusCode status;
-      UA_DateTime   sourceTimestamp;
-      UA_Int16      sourcePicoseconds;
-      UA_DateTime   serverTimestamp;
-      UA_Int16      serverPicoseconds;
-  } UA_DataValue;
-
-UA_DiagnosticInfo
-^^^^^^^^^^^^^^^^^
-
-A structure that contains detailed error and diagnostic information associated
-with a StatusCode.
-
-.. code-block:: c
-
-  typedef struct UA_DiagnosticInfo {
-      UA_Boolean    hasSymbolicId          : 1;
-      UA_Boolean    hasNamespaceUri        : 1;
-      UA_Boolean    hasLocalizedText       : 1;
-      UA_Boolean    hasLocale              : 1;
-      UA_Boolean    hasAdditionalInfo      : 1;
-      UA_Boolean    hasInnerStatusCode     : 1;
-      UA_Boolean    hasInnerDiagnosticInfo : 1;
-      UA_Int32      symbolicId;
-      UA_Int32      namespaceUri;
-      UA_Int32      localizedText;
-      UA_Int32      locale;
-      UA_String     additionalInfo;
-      UA_StatusCode innerStatusCode;
-      struct UA_DiagnosticInfo *innerDiagnosticInfo;
-  } UA_DiagnosticInfo;
-
-.. _generic-handling:
-
-Generic Data Type Handling
---------------------------
-
-All standard-defined data types are described with an ``UA_DataType`` structure.
-In addition to the 25 builtin data types, OPC UA defines many more. But they are
-mere combinations of the builtin data types. We handle all types in a unified
-way by storing their internal structure. So it is not necessary to define
-specialized functions for all additional types.
-
-The ``UA_TYPES`` array contains the description of every standard-defined data
-type.
-
-.. code-block:: c
-
-  extern const UA_DataType UA_TYPES[UA_TYPES_COUNT];
-
-The following is an excerpt from ``ua_types_generated.h`` with the definition of
-OPC UA read requests. This file is auto-generated from the XML-description of
-the OPC UA data types that is part of the ISO/IEC 62541 standard.
-
-.. code-block:: c
-
-  typedef struct {
-      UA_RequestHeader requestHeader;
-      UA_Double maxAge;
-      UA_TimestampsToReturn timestampsToReturn;
-      size_t nodesToReadSize;
-      UA_ReadValueId *nodesToRead;
-  } UA_ReadRequest;
-
-  #define UA_TYPES_READREQUEST 118
-  
-  static UA_INLINE void UA_ReadRequest_init(UA_ReadRequest *p) {
-      memset(p, 0, sizeof(UA_ReadRequest)); }
-
-  static UA_INLINE void UA_ReadRequest_delete(UA_ReadRequest *p) {
-      UA_delete(p, &UA_TYPES[UA_TYPES_READREQUEST]); }
-
-  static UA_INLINE void UA_ReadRequest_deleteMembers(UA_ReadRequest *p) {
-      UA_deleteMembers(p, &UA_TYPES[UA_TYPES_READREQUEST]); }
-
-  static UA_INLINE UA_ReadRequest * UA_ReadRequest_new(void) {
-      return (UA_ReadRequest*) UA_new(&UA_TYPES[UA_TYPES_READREQUEST]); }
-
-  static UA_INLINE UA_StatusCode
-  UA_ReadRequest_copy(const UA_ReadRequest *src, UA_ReadRequest *dst) {
-      return UA_copy(src, dst, &UA_TYPES[UA_TYPES_READREQUEST]); }
-
-.. _array-handling:
-
-Array Handling
---------------
-
-In OPC UA, all arrays can be undefined, have length 0 or a positive length. In
-data structures, all arrays are represented by a ``size_t`` length field and an
-appropriate pointer directly afterwards. In order to distinguish between
-undefined and length-zero arrays, we define the following.
-
-.. code-block:: c
-
-  #define UA_EMPTY_ARRAY_SENTINEL ((void*)0x01)
-
-- size == 0 and data == NULL: The array is undefined
-- size == 0 and data == ``UA_EMPTY_ARRAY_SENTINEL``: The array has length 0
-- size > 0: The array at the given memory address has the given size
-
-The following functions are defined for array handling.
-
-.. code-block:: c
-
-  /**
-   * Allocates and initializes an array of variables of a specific type
-   *
-   * @param size The requested array length
-   * @param type The datatype description
-   * @return Returns the memory location of the variable or (void*)0 if no memory could be allocated
-   */
-  void * UA_Array_new(size_t size, const UA_DataType *type);
-
-  /**
-   * Allocates and copies an array. dst is set to (void*)0 if not enough memory is available.
-   *
-   * @param src The memory location of the source array
-   * @param src_size The size of the array
-   * @param dst The location of the pointer to the new array
-   * @param type The datatype of the array members
-   * @return Returns whether copying succeeded
-   */
-  UA_StatusCode UA_Array_copy(const void *src, size_t src_size, void **dst,
-                              const UA_DataType *type);
-
-  /**
-   * Deletes an array.
-   *
-   * @param p The memory location of the array
-   * @param size The size of the array
-   * @param type The datatype of the array members
-   */
-  void UA_Array_delete(void *p, size_t size, const UA_DataType *type); 

+ 1 - 1
doc/index.rst

@@ -23,7 +23,7 @@ standard.
    in_a_nutshell
    building
    tutorials
-   datatypes
+   types
 
    
 Indices and tables

+ 321 - 235
include/ua_types.h

@@ -28,100 +28,209 @@ extern "C" {
 #include "ua_config.h"
 #include "ua_statuscodes.h"
 
-/* Indicates that an array has the length 0 (NULL indicates an non-defined array of length -1) */
-#define UA_EMPTY_ARRAY_SENTINEL ((void*)0x01)
-
-/****************************/
-/* Builtin Type Definitions */
-/****************************/
+/**
+ * Data Types
+ * ==========
+ *
+ * In open62541, all data types share the same basic API for creation, copying
+ * and deletion. The header ua_types.h defines the builtin types. In addition,
+ * we auto-generate ua_types_generated.h with additional types as well as the
+ * following function definitions for all (builtin and generated) data types
+ * ``T``.
+ *
+ * ``void T_init(T *ptr)``
+ *   Initialize the data type. This is synonymous with zeroing out the memory, i.e. *memset(dataptr, 0, sizeof(T))*.
+ * ``T* T_new()``
+ *   Allocate and return the memory for the data type. The memory is already initialized.
+ * ``UA_StatusCode T_copy(const T *src, T *dst)``
+ *   Copy the content of the data type. Returns *UA_STATUSCODE_GOOD* if it succeeded.
+ * ``void T_deleteMembers(T *ptr)``
+ *   Delete the dynamically allocated content of the data type, but not the data type itself.
+ * ``void T_delete(T *ptr)``
+ *   Delete the content of the data type and the memory for the data type itself.
+ *
+ * OPC UA defines 25 builtin data types. All other data types are combinations
+ * of the 25 builtin data types. */
 
 #define UA_BUILTIN_TYPES_COUNT 25U
 
-/** Boolean: A two-state logical value (true or false) */
+/**
+ * Builtin Types Part 1
+ * --------------------
+ *
+ * Boolean
+ * ^^^^^^^
+ * A two-state logical value (true or false). */
 typedef bool UA_Boolean;
 #define UA_TRUE true
 #define UA_FALSE false
 
-/** SByte: An integer value between -128 and 127 */
+/**
+ * SByte
+ * ^^^^^
+ * An integer value between -128 and 127. */
 typedef int8_t UA_SByte;
 #define UA_SBYTE_MAX 127
 #define UA_SBYTE_MIN (-128)
 
-/** Byte: An integer value between 0 and 256 */
+/**
+ * Byte
+ * ^^^^
+ * An integer value between 0 and 256. */
 typedef uint8_t UA_Byte;
 #define UA_BYTE_MAX 256
 #define UA_BYTE_MIN 0
 
-/** Int16: An integer value between -32 768 and 32 767 */
+/**
+ * Int16
+ * ^^^^^
+ * An integer value between -32 768 and 32 767. */
 typedef int16_t UA_Int16;
 #define UA_INT16_MAX 32767
 #define UA_INT16_MIN (-32768)
 
-/** UInt16: An integer value between 0 and 65 535 */
+/**
+ * UInt16
+ * ^^^^^^
+ * An integer value between 0 and 65 535. */
 typedef uint16_t UA_UInt16;
 #define UA_UINT16_MAX 65535
 #define UA_UINT16_MIN 0
 
-/** Int32: An integer value between -2 147 483 648 and 2 147 483 647 */
+/**
+ * Int32
+ * ^^^^^
+ * An integer value between -2 147 483 648 and 2 147 483 647. */
 typedef int32_t UA_Int32;
 #define UA_INT32_MAX 2147483647
 #define UA_INT32_MIN (-2147483648)
 
-/** UInt32: An integer value between 0 and 4 294 967 295 */
+/**
+ * UInt32
+ * ^^^^^^
+ * An integer value between 0 and 4 294 967 295. */
 typedef uint32_t UA_UInt32;
 #define UA_UINT32_MAX 4294967295
 #define UA_UINT32_MIN 0
 
-/* do not use for cryptographic entropy */
-UA_EXPORT UA_UInt32 UA_UInt32_random(void);
-
-/** Int64: An integer value between -10 223 372 036 854 775 808 and 9 223 372 036 854 775 807 */
+/**
+ * Int64
+ * ^^^^^
+ * An integer value between -10 223 372 036 854 775 808 and 9 223 372 036 854 775 807. */
 typedef int64_t UA_Int64;
 #define UA_INT64_MAX (int64_t)9223372036854775807
 #define UA_INT64_MIN ((int64_t)-9223372036854775808)
 
-/** UInt64: An integer value between 0 and 18 446 744 073 709 551 615 */
+/**
+ * UInt64
+ * ^^^^^^
+ * An integer value between 0 and 18 446 744 073 709 551 615. */
 typedef uint64_t UA_UInt64;
 #define UA_UINT64_MAX (int64_t)18446744073709551615
 #define UA_UINT64_MIN (int64_t)0
 
-/** Float: An IEEE single precision (32 bit) floating point value */
+/**
+ * Float
+ * ^^^^^
+ * An IEEE single precision (32 bit) floating point value. */
 typedef float UA_Float;
 
-/** Double: An IEEE double precision (64 bit) floating point value */
+/**
+ * Double
+ * ^^^^^^
+ * An IEEE double precision (64 bit) floating point value. */
 typedef double UA_Double;
 
-/** StatusCode: A numeric identifier for a error or condition that is associated with a value or an operation */
+/**
+ * StatusCode
+ * ^^^^^^^^^^
+ * A numeric identifier for a error or condition that is associated with a value
+ * or an operation. */
 typedef uint32_t UA_StatusCode;
 
-/********************************************/
-/* String: A sequence of Unicode characters */
-/********************************************/
+/**
+ * .. _array-handling:
+ *
+ * Array handling
+ * --------------
+ *
+ * In OPC UA, arrays can have a length of zero or more with the usual meaning.
+ * In addition, arrays can be undefined. Then, they don't even have a length. In
+ * the binary encoding, this is indicated by an array of length -1.
+ *
+ * In open62541 however, we use ``size_t`` for array lengths. An undefined array
+ * has length 0 and the data pointer is NULL. An array of length 0 also has
+ * length 0 but points to a sentinel memory address. */
+#define UA_EMPTY_ARRAY_SENTINEL ((void*)0x01)
+#define MAX_ARRAY_SIZE 104857600 // arrays must be smaller than 100MB
+
+/** Forward Declaration of UA_DataType. See Section `Generic Type Handling`_
+    for details. */
+struct UA_DataType;
+typedef struct UA_DataType UA_DataType; 
+
+/** The following functions are used for handling arrays of an data type. */
+
+/* Allocates and initializes an array of variables of a specific type
+ *
+ * @param size The requested array length
+ * @param type The datatype description
+ * @return Returns the memory location of the variable or (void*)0 if no memory
+           could be allocated */
+void UA_EXPORT * UA_Array_new(size_t size, const UA_DataType *type) UA_FUNC_ATTR_MALLOC;
+
+/* Allocates and copies an array
+ *
+ * @param src The memory location of the source array
+ * @param size The size of the array
+ * @param dst The location of the pointer to the new array
+ * @param type The datatype of the array members
+ * @return Returns UA_STATUSCODE_GOOD or UA_STATUSCODE_BADOUTOFMEMORY */
+UA_StatusCode UA_EXPORT UA_Array_copy(const void *src, size_t size, void **dst, const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+/* Deletes an array.
+ *
+ * @param p The memory location of the array
+ * @param size The size of the array
+ * @param type The datatype of the array members */
+void UA_EXPORT UA_Array_delete(void *p, size_t size, const UA_DataType *type);
+
+/**
+ * Builtin Types, Part 2
+ * ---------------------
+ *
+ * String
+ * ^^^^^^
+ * A sequence of Unicode characters. Strings are just an array of UA_Byte. */
 typedef struct {
-    size_t length; // The length of the string
-    UA_Byte *data; // The string's content (not null-terminated)
+    size_t length; /* The length of the string */
+    UA_Byte *data; /* The content (not null-terminated) */
 } UA_String;
 
+/* Copies the content on the heap. Returns a null-string when alloc fails */
+UA_String UA_EXPORT UA_String_fromChars(char const src[]) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+
+UA_Boolean UA_EXPORT UA_String_equal(const UA_String *s1, const UA_String *s2);
+
 UA_EXPORT extern const UA_String UA_STRING_NULL;
 
+/**
+ * ``UA_STRING`` returns a string pointing to the preallocated char-array.
+ * ``UA_STRING_ALLOC`` is shorthand for ``UA_String_fromChars`` and makes a copy
+ * of the char-array. */
 static UA_INLINE UA_String UA_STRING(char *chars) {
     UA_String str; str.length = strlen(chars);
     str.data = (UA_Byte*)chars; return str; }
 
 #define UA_STRING_ALLOC(CHARS) UA_String_fromChars(CHARS)
-    
-/** Copies the content on the heap. Returns a null-string when alloc fails */
-UA_String UA_EXPORT UA_String_fromChars(char const src[]) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
-
-UA_Boolean UA_EXPORT UA_String_equal(const UA_String *s1, const UA_String *s2);
 
-/*********************************/
-/* DateTime: An instance in time */
-/*********************************/
-
-/* A DateTime value is encoded as a 64-bit signed integer which represents the
-   number of 100 nanosecond intervals since January 1, 1601 (UTC) */
-typedef UA_Int64 UA_DateTime;
+/**
+ * DateTime
+ * ^^^^^^^^
+ * An instance in time. A DateTime value is encoded as a 64-bit signed integer
+ * which represents the number of 100 nanosecond intervals since January 1, 1601
+ * (UTC). */
+typedef int64_t UA_DateTime;
 
 /* Multiply to convert units for time difference computations */
 #define UA_USEC_TO_DATETIME 10LL
@@ -153,9 +262,10 @@ UA_DateTimeStruct UA_EXPORT UA_DateTime_toStruct(UA_DateTime t);
 
 UA_String UA_EXPORT UA_DateTime_toString(UA_DateTime t);
 
-/**************************************************************************/
-/* Guid: A 16 byte value that can be used as a globally unique identifier */
-/**************************************************************************/
+/**
+ * Guid
+ * ^^^^
+ * A 16 byte value that can be used as a globally unique identifier. */
 typedef struct {
     UA_UInt32 data1;
     UA_UInt16 data2;
@@ -168,9 +278,10 @@ UA_Boolean UA_EXPORT UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2);
 /* do not use for cryptographic entropy */
 UA_Guid UA_EXPORT UA_Guid_random(void);
 
-/************************************/
-/* ByteString: A sequence of octets */
-/************************************/
+/**
+ * ByteString
+ * ^^^^^^^^^^
+ * A sequence of octets. */
 typedef UA_String UA_ByteString;
 
 static UA_INLINE UA_Boolean
@@ -190,16 +301,20 @@ static UA_INLINE UA_ByteString UA_BYTESTRING_ALLOC(const char *chars) {
     bstr.length = str.length; bstr.data = str.data; return bstr;
 }
 
-/******************************/
-/* XmlElement: An XML element */
-/******************************/
+/**
+ * XmlElement
+ * ^^^^^^^^^^
+ * An XML element. */
 typedef UA_String UA_XmlElement;
 
-/*****************************************************************************/
-/* NodeId: An identifier for a node in the address space of an OPC UA Server */
-/*****************************************************************************/
+/**
+ * NodeId
+ * ^^^^^^
+ * An identifier for a node in the address space of an OPC UA Server. */
 enum UA_NodeIdType {
-    UA_NODEIDTYPE_NUMERIC    = 0, ///< On the wire, this can be 0,1,2 for numeric nodeids of different sizes
+    UA_NODEIDTYPE_NUMERIC    = 0, /* In the binary encoding, this can become 0
+                                     or 1 for 2byte and 4byte encoding of small
+                                     nodeids. */
     UA_NODEIDTYPE_STRING     = 3,
     UA_NODEIDTYPE_GUID       = 4,
     UA_NODEIDTYPE_BYTESTRING = 5
@@ -225,6 +340,7 @@ static UA_INLINE UA_Boolean UA_NodeId_isNull(const UA_NodeId *p) {
 
 UA_Boolean UA_EXPORT UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2);
 
+/** The following functions are shorthand for creating NodeIds. */
 static UA_INLINE UA_NodeId UA_NODEID_NUMERIC(UA_UInt16 nsIndex, UA_UInt32 identifier) {
     UA_NodeId id; id.namespaceIndex = nsIndex; id.identifierType = UA_NODEIDTYPE_NUMERIC;
     id.identifier.numeric = identifier; return id; }
@@ -249,89 +365,106 @@ static UA_INLINE UA_NodeId UA_NODEID_BYTESTRING_ALLOC(UA_UInt16 nsIndex, const c
     UA_NodeId id; id.namespaceIndex = nsIndex; id.identifierType = UA_NODEIDTYPE_BYTESTRING;
     id.identifier.byteString = UA_BYTESTRING_ALLOC(chars); return id; }
 
-/**********************************************************************************************/
-/* ExpandedNodeId: A NodeId that allows the namespace URI to be specified instead of an index */
-/**********************************************************************************************/
+/**
+ * ExpandedNodeId
+ * ^^^^^^^^^^^^^^
+ * A NodeId that allows the namespace URI to be specified instead of an index. */
 typedef struct {
     UA_NodeId nodeId;
     UA_String namespaceUri;
     UA_UInt32 serverIndex;
 } UA_ExpandedNodeId;
 
-static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_NUMERIC(UA_UInt16 nsIndex, UA_UInt32 identifier) {
+/** The following functions are shorthand for creating ExpandedNodeIds. */
+static UA_INLINE UA_ExpandedNodeId
+UA_EXPANDEDNODEID_NUMERIC(UA_UInt16 nsIndex, UA_UInt32 identifier) {
     UA_ExpandedNodeId id; id.nodeId = UA_NODEID_NUMERIC(nsIndex, identifier);
     id.serverIndex = 0; id.namespaceUri = UA_STRING_NULL; return id; }
 
-static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_STRING(UA_UInt16 nsIndex, char *chars) {
+static UA_INLINE UA_ExpandedNodeId
+UA_EXPANDEDNODEID_STRING(UA_UInt16 nsIndex, char *chars) {
     UA_ExpandedNodeId id; id.nodeId = UA_NODEID_STRING(nsIndex, chars);
     id.serverIndex = 0; id.namespaceUri = UA_STRING_NULL; return id; }
 
-static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_STRING_ALLOC(UA_UInt16 nsIndex, const char *chars) {
+static UA_INLINE UA_ExpandedNodeId
+UA_EXPANDEDNODEID_STRING_ALLOC(UA_UInt16 nsIndex, const char *chars) {
     UA_ExpandedNodeId id; id.nodeId = UA_NODEID_STRING_ALLOC(nsIndex, chars);
     id.serverIndex = 0; id.namespaceUri = UA_STRING_NULL; return id; }
 
-static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_STRING_GUID(UA_UInt16 nsIndex, UA_Guid guid) {
+static UA_INLINE UA_ExpandedNodeId
+UA_EXPANDEDNODEID_STRING_GUID(UA_UInt16 nsIndex, UA_Guid guid) {
     UA_ExpandedNodeId id; id.nodeId = UA_NODEID_GUID(nsIndex, guid);
     id.serverIndex = 0; id.namespaceUri = UA_STRING_NULL; return id; }
 
-static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_BYTESTRING(UA_UInt16 nsIndex, char *chars) {
+static UA_INLINE UA_ExpandedNodeId
+UA_EXPANDEDNODEID_BYTESTRING(UA_UInt16 nsIndex, char *chars) {
     UA_ExpandedNodeId id; id.nodeId = UA_NODEID_BYTESTRING(nsIndex, chars);
     id.serverIndex = 0; id.namespaceUri = UA_STRING_NULL; return id; }
 
-static UA_INLINE UA_ExpandedNodeId UA_EXPANDEDNODEID_BYTESTRING_ALLOC(UA_UInt16 nsIndex, const char *chars) {
+static UA_INLINE UA_ExpandedNodeId
+UA_EXPANDEDNODEID_BYTESTRING_ALLOC(UA_UInt16 nsIndex, const char *chars) {
     UA_ExpandedNodeId id; id.nodeId = UA_NODEID_BYTESTRING_ALLOC(nsIndex, chars);
     id.serverIndex = 0; id.namespaceUri = UA_STRING_NULL; return id; }
 
-/**************************************************/
-/* QualifiedName: A name qualified by a namespace */
-/**************************************************/
+/**
+ * QualifiedName
+ * ^^^^^^^^^^^^^
+ * A name qualified by a namespace. */
 typedef struct {
     UA_UInt16 namespaceIndex;
     UA_String name;
 } UA_QualifiedName;
 
-static UA_INLINE UA_QualifiedName UA_QUALIFIEDNAME(UA_UInt16 nsIndex, char *chars) {
-    UA_QualifiedName qn; qn.namespaceIndex = nsIndex; qn.name = UA_STRING(chars); return qn; }
+static UA_INLINE UA_QualifiedName
+UA_QUALIFIEDNAME(UA_UInt16 nsIndex, char *chars) {
+    UA_QualifiedName qn; qn.namespaceIndex = nsIndex;
+    qn.name = UA_STRING(chars); return qn; }
 
-static UA_INLINE UA_QualifiedName UA_QUALIFIEDNAME_ALLOC(UA_UInt16 nsIndex, const char *chars) {
-    UA_QualifiedName qn; qn.namespaceIndex = nsIndex; qn.name = UA_STRING_ALLOC(chars); return qn; }
+static UA_INLINE UA_QualifiedName
+UA_QUALIFIEDNAME_ALLOC(UA_UInt16 nsIndex, const char *chars) {
+    UA_QualifiedName qn; qn.namespaceIndex = nsIndex;
+    qn.name = UA_STRING_ALLOC(chars); return qn; }
 
-/*************************************************************************/
-/* LocalizedText: Human readable text with an optional locale identifier */
-/*************************************************************************/
+/**
+ * LocalizedText
+ * ^^^^^^^^^^^^^
+ * Human readable text with an optional locale identifier. */
 typedef struct {
     UA_String locale;
     UA_String text;
 } UA_LocalizedText;
 
-static UA_INLINE UA_LocalizedText UA_LOCALIZEDTEXT(char *locale, char *text) {
+static UA_INLINE UA_LocalizedText
+UA_LOCALIZEDTEXT(char *locale, char *text) {
     UA_LocalizedText lt; lt.locale = UA_STRING(locale);
     lt.text = UA_STRING(text); return lt; }
 
-static UA_INLINE UA_LocalizedText UA_LOCALIZEDTEXT_ALLOC(const char *locale, const char *text) {
+static UA_INLINE UA_LocalizedText
+UA_LOCALIZEDTEXT_ALLOC(const char *locale, const char *text) {
     UA_LocalizedText lt; lt.locale = UA_STRING_ALLOC(locale);
     lt.text = UA_STRING_ALLOC(text); return lt; }
 
-/* Forward Declaration of UA_DataType */
-struct UA_DataType;
-typedef struct UA_DataType UA_DataType; 
-
-/********************************************************************************/
-/* ExtensionObject: A structure that contains an application specific data type */
-/* that may not be recognized by the receiver                                   */
-/********************************************************************************/
+/**
+ * ExtensionObject
+ * ^^^^^^^^^^^^^^^
+ * ExtensionObjects may contain scalars of any data type. Even those that are
+ * unknown to the receiver. See the Section `Generic Type Handling`_ on how
+ * types are described. An ExtensionObject always contains the NodeId of the
+ * Data Type. If the data cannot be decoded, we keep the encoded string and the
+ * NodeId. */
 typedef struct {
     enum {
         UA_EXTENSIONOBJECT_ENCODED_NOBODY     = 0,
         UA_EXTENSIONOBJECT_ENCODED_BYTESTRING = 1,
         UA_EXTENSIONOBJECT_ENCODED_XML        = 2,
-        UA_EXTENSIONOBJECT_DECODED            = 3, ///< There is a pointer to the decoded data
-        UA_EXTENSIONOBJECT_DECODED_NODELETE   = 4  ///< Don't delete the decoded data at the lifecycle end
+        UA_EXTENSIONOBJECT_DECODED            = 3,
+        UA_EXTENSIONOBJECT_DECODED_NODELETE   = 4 /* Don't delete the decoded content
+                                                     at the lifecycle end */
     } encoding;
     union {
         struct {
-            UA_NodeId typeId; ///< The nodeid of the datatype
-            UA_ByteString body; ///< The bytestring of the encoded data
+            UA_NodeId typeId;   /* The nodeid of the datatype */
+            UA_ByteString body; /* The bytestring of the encoded data */
         } encoded;
         struct {
             const UA_DataType *type;
@@ -340,17 +473,31 @@ typedef struct {
     } content;
 } UA_ExtensionObject;
 
-/*********************************************/
-/* Variant: Stores (arrays of) any data type */
-/*********************************************/
- /* Variant semantics:
-    - arrayLength == 0 && data == NULL: no existing data
-    - arrayLength == 0 && data == 0x01: array of length 0
-    - arrayLength == 0 && data > 0x01: scalar value
-    - arrayLength > 0: array of the given length
- */
+/**
+ * Variant
+ * ^^^^^^^
+ * Variants may contain data of any type. See the Section `Generic Type
+ * Handling`_ on how types are described. If the data is not of one of the 25
+ * builtin types, it will be encoded as an `ExtensionObject`_ on the wire. (The
+ * standard says that a variant is a union of the built-in types. open62541
+ * generalizes this to any data type by transparently de- and encoding
+ * ExtensionObjects in the background. If the decoding fails, the variant
+ * contains the original ExtensionObject.)
+ *
+ * Variants can contain a single scalar or an array. For details on the handling
+ * of arrays, see the Section `Array Handling`_. Array variants can have an
+ * additional dimensionality (matrix, 3-tensor, ...) defined in an array of
+ * dimension sizes. Higher rank dimensions are serialized first.
+ *
+ * The differentiation between variants containing a scalar, an array or no data
+ * is as follows:
+ *
+ * - arrayLength == 0 && data == NULL: no existing data
+ * - arrayLength == 0 && data == UA_EMPTY_ARRAY_SENTINEL: array of length 0
+ * - arrayLength == 0 && data > UA_EMPTY_ARRAY_SENTINEL: scalar value
+ * - arrayLength > 0: array of the given length */
 typedef struct {
-    const UA_DataType *type; // The data type description
+    const UA_DataType *type; /* The data type description */
     enum {
         UA_VARIANT_DATA,          /* The data has the same lifecycle as the variant */
         UA_VARIANT_DATA_NODELETE, /* The data is "borrowed" by the variant and shall not be
@@ -362,65 +509,51 @@ typedef struct {
     UA_UInt32 *arrayDimensions; // The length of each dimension of the data-array
 } UA_Variant;
 
-/**
- * Returns true if the variant contains a scalar value. Note that empty variants
+/* Returns true if the variant contains a scalar value. Note that empty variants
  * contain an array of length -1 (undefined).
- *
  * @param v The variant
- * @return Does the variant contain a scalar value.
- */
+ * @return Does the variant contain a scalar value. */
 static UA_INLINE UA_Boolean UA_Variant_isScalar(const UA_Variant *v) {
     return (v->arrayLength == 0 && v->data > UA_EMPTY_ARRAY_SENTINEL); }
     
-/**
- * Set the variant to a scalar value that already resides in memory. The value
+/* Set the variant to a scalar value that already resides in memory. The value
  * takes on the lifecycle of the variant and is deleted with it.
- *
  * @param v The variant
  * @param p A pointer to the value data
- * @param type The datatype of the value in question
- */
+ * @param type The datatype of the value in question */
 void UA_EXPORT
 UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p, const UA_DataType *type);
 
-/**
- * Set the variant to a scalar value that is copied from an existing variable.
- *
+/* Set the variant to a scalar value that is copied from an existing variable.
  * @param v The variant
  * @param p A pointer to the value data
  * @param type The datatype of the value
- * @return Indicates whether the operation succeeded or returns an error code
- */
+ * @return Indicates whether the operation succeeded or returns an error code */
 UA_StatusCode UA_EXPORT
 UA_Variant_setScalarCopy(UA_Variant *v, const void *p, const UA_DataType *type);
 
-/**
- * Set the variant to an array that already resides in memory. The array takes
+/* Set the variant to an array that already resides in memory. The array takes
  * on the lifecycle of the variant and is deleted with it.
- *
  * @param v The variant
  * @param array A pointer to the array data
  * @param arraySize The size of the array
- * @param type The datatype of the array
- */
+ * @param type The datatype of the array */
 void UA_EXPORT
 UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
                     size_t arraySize, const UA_DataType *type);
 
-/**
- * Set the variant to an array that is copied from an existing array.
- *
+/* Set the variant to an array that is copied from an existing array.
  * @param v The variant
  * @param array A pointer to the array data
  * @param arraySize The size of the array
  * @param type The datatype of the array
- * @return Indicates whether the operation succeeded or returns an error code
- */
+ * @return Indicates whether the operation succeeded or returns an error code */
 UA_StatusCode UA_EXPORT
 UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
                         size_t arraySize, const UA_DataType *type);
 
-/* NumericRanges are used to indicate subsets of a (multidimensional) variant
+/**
+ * NumericRanges are used to indicate subsets of a (multidimensional) variant
  * array. NumericRange has no official type structure in the standard. On the
  * wire, it only exists as an encoded string, such as "1:2,0:3,5". The colon
  * separates min/max index and the comma separates dimensions. A single value
@@ -433,20 +566,16 @@ typedef struct {
     } *dimensions;
 } UA_NumericRange;
 
-/**
- * Copy the variant, but use only a subset of the (multidimensional) array into a variant. Returns
+/* Copy the variant, but use only a subset of the (multidimensional) array into a variant. Returns
  * an error code if the variant is not an array or if the indicated range does not fit.
- *
  * @param src The source variant
  * @param dst The target variant
  * @param range The range of the copied data
- * @return Returns UA_STATUSCODE_GOOD or an error code
- */
+ * @return Returns UA_STATUSCODE_GOOD or an error code */
 UA_StatusCode UA_EXPORT
 UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst, const UA_NumericRange range);
 
-/**
- * Insert a range of data into an existing variant. The data array can't be reused afterwards if it
+/* Insert a range of data into an existing variant. The data array can't be reused afterwards if it
  * contains types without a fixed size (e.g. strings) since the members are moved into the variant
  * and take on its lifecycle.
  *
@@ -454,28 +583,26 @@ UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst, const UA_NumericRan
  * @param dataArray The data array. The type must match the variant
  * @param dataArraySize The length of the data array. This is checked to match the range size.
  * @param range The range of where the new data is inserted
- * @return Returns UA_STATUSCODE_GOOD or an error code
- */
+ * @return Returns UA_STATUSCODE_GOOD or an error code */
 UA_StatusCode UA_EXPORT
 UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array,
                     size_t arraySize, const UA_NumericRange range);
 
-/**
- * Deep-copy a range of data into an existing variant.
+/* Deep-copy a range of data into an existing variant.
  *
  * @param v The variant
  * @param dataArray The data array. The type must match the variant
  * @param dataArraySize The length of the data array. This is checked to match the range size.
  * @param range The range of where the new data is inserted
- * @return Returns UA_STATUSCODE_GOOD or an error code
- */
+ * @return Returns UA_STATUSCODE_GOOD or an error code */
 UA_StatusCode UA_EXPORT
 UA_Variant_setRangeCopy(UA_Variant *v, const void *array,
                         size_t arraySize, const UA_NumericRange range);
 
-/**************************************************************************/
-/* DataValue: A data value with an associated status code and timestamps. */
-/**************************************************************************/
+/**
+ * DataValue
+ * ^^^^^^^^^
+ * A data value with an associated status code and timestamps. */
 typedef struct {
     UA_Boolean    hasValue             : 1;
     UA_Boolean    hasStatus            : 1;
@@ -491,10 +618,11 @@ typedef struct {
     UA_UInt16     serverPicoseconds;
 } UA_DataValue;
 
-/***************************************************************************/
-/* DiagnosticInfo: A structure that contains detailed error and diagnostic */
-/* information associated with a StatusCode.                               */
-/***************************************************************************/
+/**
+ * DiagnosticInfo
+ * ^^^^^^^^^^^^^^
+ * A structure that contains detailed error and diagnostic information
+ * associated with a StatusCode. */
 typedef struct UA_DiagnosticInfo {
     UA_Boolean    hasSymbolicId          : 1;
     UA_Boolean    hasNamespaceUri        : 1;
@@ -512,130 +640,90 @@ typedef struct UA_DiagnosticInfo {
     struct UA_DiagnosticInfo *innerDiagnosticInfo;
 } UA_DiagnosticInfo;
 
-/*************************/
-/* Generic Type Handling */
-/*************************/
-
+/**
+ * .. _generic-handling:
+ *
+ * Generic Type Handling
+ * ---------------------
+ * The builtin types can be combined to data structures. All information about a
+ * (structured) data type is stored in a ``UA_DataType``. The array ``UA_TYPES``
+ * contains the description of all standard-defined types and is used for
+ * handling of generic types. */
 typedef struct {
 #ifdef UA_ENABLE_TYPENAMES
     const char *memberName;
 #endif
-    UA_UInt16   memberTypeIndex;   ///< Index of the member in the datatypetable
-    UA_Byte     padding;           /**< How much padding is there before this member
-                                        element? For arrays this is the padding before the
-                                        size_t lenght member. (No padding between size_t
-                                        and the following ptr.) */
-    UA_Boolean  namespaceZero : 1; /**< The type of the member is defined in namespace
-                                        zero. In this implementation, types from custom
-                                        namespace may contain members from the same
-                                        namespace or ns0 only.*/
-    UA_Boolean  isArray       : 1; ///< The member is an array of the given type
+    UA_UInt16   memberTypeIndex;   /* Index of the member in the array of data types */
+    UA_Byte     padding;           /* How much padding is there before this member
+                                      element? For arrays this is the padding before the
+                                      size_t lenght member. (No padding between size_t and
+                                      the following ptr.) */
+    UA_Boolean  namespaceZero : 1; /* The type of the member is defined in namespace zero.
+                                      In this implementation, types from custom namespace
+                                      may contain members from the same namespace or ns0
+                                      only.*/
+    UA_Boolean  isArray       : 1; /* The member is an array */
 } UA_DataTypeMember;
     
 struct UA_DataType {
 #ifdef UA_ENABLE_TYPENAMES
     const char *typeName;
 #endif
-    UA_NodeId   typeId;           ///< The nodeid of the type
-    UA_UInt16   memSize;          ///< Size of the struct in memory
-    UA_UInt16   typeIndex;        ///< Index of the type in the datatypetable
-    UA_Byte     membersSize;      ///< How many members does the type have?
-    UA_Boolean  builtin      : 1; ///< The type is "builtin" and has dedicated de- and encoding functions
-    UA_Boolean  fixedSize    : 1; ///< The type (and its members) contains no pointers
-    UA_Boolean  zeroCopyable : 1; ///< The type can be copied directly off the stream (given that the endianness matches)
+    UA_NodeId   typeId;           /* The nodeid of the type */
+    UA_UInt16   memSize;          /* Size of the struct in memory */
+    UA_UInt16   typeIndex;        /* Index of the type in the datatypetable */
+    UA_Byte     membersSize;      /* How many members does the type have? */
+    UA_Boolean  builtin      : 1; /* The type is "builtin" and has dedicated de- and
+                                     encoding functions */
+    UA_Boolean  fixedSize    : 1; /* The type (and its members) contains no pointers */
+    UA_Boolean  zeroCopyable : 1; /* The type can be copied directly off the stream (given
+                                     that the endianness matches) */
     UA_DataTypeMember *members;
 };
 
-/**
- * Allocates and initializes a variable of type dataType
+/** The following functions are used for generic handling of data types. */
+
+/* Allocates and initializes a variable of type dataType
  *
  * @param type The datatype description
- * @return Returns the memory location of the variable or (void*)0 if no memory is available
- */
+ * @return Returns the memory location of the variable or (void*)0 if no memory is available */
 void UA_EXPORT * UA_new(const UA_DataType *type) UA_FUNC_ATTR_MALLOC;
 
-/**
- * Initializes a variable to default values
+/* Initializes a variable to default values
  *
  * @param p The memory location of the variable
- * @param type The datatype description
- */
-static UA_INLINE void UA_init(void *p, const UA_DataType *type) {
-    memset(p, 0, type->memSize); }
+ * @param type The datatype description */
+static UA_INLINE void
+UA_init(void *p, const UA_DataType *type) { memset(p, 0, type->memSize); }
 
-/**
- * Copies the content of two variables. If copying fails (e.g. because no memory was available for
- * an array), then dst is emptied and initialized to prevent memory leaks.
+/* Copies the content of two variables. If copying fails (e.g. because no memory was
+ * available for an array), then dst is emptied and initialized to prevent memory leaks.
  *
  * @param src The memory location of the source variable
  * @param dst The memory location of the destination variable
  * @param type The datatype description
- * @return Indicates whether the operation succeeded or returns an error code
- */
-UA_StatusCode UA_EXPORT
-UA_copy(const void *src, void *dst, const UA_DataType *type);
+ * @return Indicates whether the operation succeeded or returns an error code */
+UA_StatusCode UA_EXPORT UA_copy(const void *src, void *dst, const UA_DataType *type);
 
-/**
- * Deletes the dynamically assigned content of a variable (e.g. a member-array).
- * Afterwards, the variable can be safely deleted without causing memory leaks.
- * But the variable is not initialized and may contain old data that is not
+/* Deletes the dynamically allocated content of a variable (e.g. resets all arrays to
+ * undefined arrays). Afterwards, the variable can be safely deleted without causing
+ * memory leaks. But the variable is not initialized and may contain old data that is not
  * memory-relevant.
  *
  * @param p The memory location of the variable
- * @param type The datatype description of the variable
- */
+ * @param type The datatype description of the variable */
 void UA_EXPORT UA_deleteMembers(void *p, const UA_DataType *type);
 
-/**
- * Deletes (frees) a variable and all of its content.
+/* Frees a variable and all of its content.
  *
  * @param p The memory location of the variable
- * @param type The datatype description of the variable
- */
+ * @param type The datatype description of the variable */
 void UA_EXPORT UA_delete(void *p, const UA_DataType *type);
 
-/********************/
-/* Array operations */
-/********************/
-
-#define MAX_ARRAY_SIZE 104857600 // arrays must be smaller than 100MB
-
-/**
- * Allocates and initializes an array of variables of a specific type
- *
- * @param size The requested array length
- * @param type The datatype description
- * @return Returns the memory location of the variable or (void*)0 if no memory could be allocated
- */
-void UA_EXPORT * UA_Array_new(size_t size, const UA_DataType *type) UA_FUNC_ATTR_MALLOC;
-
 /**
- * Allocates and copies an array. dst is set to (void*)0 if not enough memory is available.
- *
- * @param src The memory location of the source array
- * @param src_size The size of the array
- * @param dst The location of the pointer to the new array
- * @param type The datatype of the array members
- * @return Returns whether copying succeeded
- */
-UA_StatusCode UA_EXPORT
-UA_Array_copy(const void *src, size_t src_size, void **dst,
-              const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
-
-/**
- * Deletes an array.
- *
- * @param p The memory location of the array
- * @param size The size of the array
- * @param type The datatype of the array members
- */
-void UA_EXPORT UA_Array_delete(void *p, size_t size, const UA_DataType *type);
-
-/**********************/
-/* Node Attribute Ids */
-/**********************/
-
-/* These are not generated from XML. Server *and* client need them. */
+ * Standard-defined constants
+ * --------------------------
+ * These are not generated from XML. Server *and* client need them. */
 typedef enum {
     UA_ATTRIBUTEID_NODEID                  = 1,
     UA_ATTRIBUTEID_NODECLASS               = 2,
@@ -669,15 +757,13 @@ typedef enum {
     UA_ACCESSLEVELMASK_SEMANTICCHANGE = 0x10
 } UA_AccessLevelMask;
 
-/***************************/
-/* Random Number Generator */
-/***************************/
-
 /**
+ * Random Number Generator
+ * -----------------------
  * If UA_ENABLE_MULTITHREADING is defined, then the seed is stored in thread local
- * storage. The seed is initialized for every thread in the server/client.
- */
+ * storage. The seed is initialized for every thread in the server/client. */
 UA_EXPORT void UA_random_seed(UA_UInt64 seed);
+UA_EXPORT UA_UInt32 UA_UInt32_random(void); /* do not use for cryptographic entropy */
 
 #ifdef __cplusplus
 } // extern "C"

+ 81 - 0
tools/c2rst.py

@@ -0,0 +1,81 @@
+import sys
+import os
+import binascii
+import re
+
+remove_keyword = [" UA_EXPORT", " UA_FUNC_ATTR_WARN_UNUSED_RESULT",
+                  " UA_FUNC_ATTR_MALLOC"]
+
+def clean_comment(line):
+    m = re.search("^( \* |/\*\* )(.*?)( \*/)?$", line)
+    if not m:
+        return "\n"
+    return m.group(2) + "\n"
+
+def clean_line(line):
+    for keyword in remove_keyword:
+        line = line.replace(keyword, "")
+    return line
+
+def comment_start(line):
+    m = re.search("^/\*\*[ \n]", line)
+    if not m:
+        return False
+    return True
+
+def comment_end(line):
+    m = re.search(" \*/$", line)
+    if not m:
+        return False
+    return True
+
+def first_line(c):
+    "Searches for the first comment"
+    for i in range(len(c)):
+        if comment_start(c[i]):
+            return i
+    return -1
+
+def last_line(c):
+    "Searches for the latest ifdef (closing the include guard)"
+    last = 1
+    for i in range(1, len(c)):
+        m = re.search("^#ifdef", c[i])
+        if m:
+            last = i
+    return last
+
+if len(sys.argv) < 2:
+    print("Usage: python c2rst.py input.c/h output.rst")
+    exit(0)
+
+with open(sys.argv[1]) as f:
+    c = f.readlines()
+
+with open(sys.argv[2], 'w') as rst:
+    in_doc = False
+    for i in range(first_line(c), last_line(c)):
+        line = c[i]
+        doc_start = False
+        doc_end = False
+        if in_doc:
+            doc_end = comment_end(line)
+            line = clean_comment(line)
+        else:
+            doc_start = comment_start(line)
+            if doc_start:
+                doc_end = comment_end(line)
+                line = clean_comment(line)
+
+        if doc_start:
+            in_doc = True
+
+        if not ((doc_start or doc_end) and line == "\n"):
+            if not in_doc:
+                line = "   " + line
+            rst.write(clean_line(line))
+
+        if doc_end:
+            rst.write("\n.. code-block:: c\n\n")
+            in_doc = False
+    rst.write("\n")

+ 14 - 11
tools/travis_push_doc.sh

@@ -1,14 +1,17 @@
 #!/bin/bash
 
-git clone --depth=5 -b gh-pages https://$GITAUTH@github.com/open62541/open62541-www
-cd open62541-www
+BRANCH="$(git rev-parse --abbrev-ref HEAD)"
+if [ "$BRANCH" == "master" ]; then
+    git clone --depth=5 -b gh-pages https://$GITAUTH@github.com/open62541/open62541-www
+    cd open62541-www
 
-git rm -r -f ./doc/current/*
-cp -r ../../doc/* ./doc/current/
-git add -A ./doc/current
-git config --global user.email "open62541-travis-ci@users.noreply.github.com"
-git config --global user.name "Open62541 travis-ci"
-git config --global push.default simple
-git commit -am "updated generated documentation on webpage by travis-ci [ci skip]"
-git push https://$GITAUTH@github.com/open62541/open62541-www
-cd .. && rm -rf open62541-www
+    git rm -r -f ./doc/current/*
+    cp -r ../../doc_html/* ./doc/current/
+    git add -A ./doc/current
+    git config --global user.email "open62541-travis-ci@users.noreply.github.com"
+    git config --global user.name "Open62541 travis-ci"
+    git config --global push.default simple
+    git commit -am "updated generated documentation on webpage by travis-ci [ci skip]"
+    git push https://$GITAUTH@github.com/open62541/open62541-www
+    cd .. && rm -rf open62541-www
+fi