LCOV - code coverage report
Current view: top level - capi-machine-learning-inference-1.8.8/c/src - ml-api-common.c (source / functions) Coverage Total Hit
Test: ML API 1.8.8-0 platform/core/api/machine-learning#7ead26abf0b72fa637f03f66fcb47a7802e6e462 Lines: 6.7 % 774 52
Test Date: 2026-09-02 21:31:28 Functions: 13.3 % 60 8

            Line data    Source code
       1              : /* SPDX-License-Identifier: Apache-2.0 */
       2              : /**
       3              :  * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved.
       4              :  *
       5              :  * @file nnstreamer-capi-util.c
       6              :  * @date 10 June 2019
       7              :  * @brief NNStreamer/Utilities C-API Wrapper.
       8              :  * @see https://github.com/nnstreamer/nnstreamer
       9              :  * @author MyungJoo Ham <myungjoo.ham@samsung.com>
      10              :  * @bug No known bugs except for NYI items
      11              :  */
      12              : 
      13              : #include <string.h>
      14              : #include <stdio.h>
      15              : #include <stdarg.h>
      16              : #include <glib.h>
      17              : #include <nnstreamer_plugin_api_util.h>
      18              : #include "nnstreamer.h"
      19              : #include "nnstreamer-tizen-internal.h"
      20              : #include "ml-api-internal.h"
      21              : 
      22              : /**
      23              :  * @brief Enumeration for ml_info type.
      24              :  */
      25              : typedef enum
      26              : {
      27              :   ML_INFO_TYPE_UNKNOWN = 0,
      28              :   ML_INFO_TYPE_OPTION = 0xfeed0001,
      29              :   ML_INFO_TYPE_INFORMATION = 0xfeed0010,
      30              :   ML_INFO_TYPE_INFORMATION_LIST = 0xfeed0011,
      31              : 
      32              :   ML_INFO_TYPE_MAX = 0xfeedffff
      33              : } ml_info_type_e;
      34              : 
      35              : /**
      36              :  * @brief Data structure for value of ml_info.
      37              :  */
      38              : typedef struct
      39              : {
      40              :   void *value; /**< The data given by user. */
      41              :   ml_data_destroy_cb destroy; /**< The destroy func given by user. */
      42              : } ml_info_value_s;
      43              : 
      44              : /**
      45              :  * @brief Data structure for ml_info.
      46              :  */
      47              : typedef struct
      48              : {
      49              :   ml_info_type_e type; /**< The type of ml_info. */
      50              :   GHashTable *table; /**< hash table used by ml_info. */
      51              : } ml_info_s;
      52              : 
      53              : /**
      54              :  * @brief Data structure for ml_info_list.
      55              :  */
      56              : typedef struct
      57              : {
      58              :   ml_info_type_e type; /**< The type of ml_info. */
      59              :   GSList *info; /**< The list of ml_info. */
      60              : } ml_info_list_s;
      61              : 
      62              : /**
      63              :  * @brief Internal data structure for iterating ml-information.
      64              :  */
      65              : typedef struct
      66              : {
      67              :   ml_information_iterate_cb callback;
      68              :   void *user_data;
      69              : } ml_info_iter_data_s;
      70              : 
      71              : /**
      72              :  * @brief Gets the version number of machine-learning API.
      73              :  */
      74              : void
      75            0 : ml_api_get_version (unsigned int *major, unsigned int *minor,
      76              :     unsigned int *micro)
      77              : {
      78            0 :   if (major)
      79            0 :     *major = VERSION_MAJOR;
      80            0 :   if (minor)
      81            0 :     *minor = VERSION_MINOR;
      82            0 :   if (micro)
      83            0 :     *micro = VERSION_MICRO;
      84            0 : }
      85              : 
      86              : /**
      87              :  * @brief Convert the type from ml_tensor_type_e to tensor_type.
      88              :  * @note This code is based on the same order between NNS type and ML type.
      89              :  * The index should be the same in case of adding a new type.
      90              :  */
      91              : static tensor_type
      92            0 : convert_tensor_type_from (ml_tensor_type_e type)
      93              : {
      94            0 :   if (type < ML_TENSOR_TYPE_INT32 || type >= ML_TENSOR_TYPE_UNKNOWN) {
      95            0 :     _ml_error_report
      96              :         ("Failed to convert the type. Input ml_tensor_type_e %d is invalid.",
      97              :         type);
      98            0 :     return _NNS_END;
      99              :   }
     100              : 
     101            0 :   return (tensor_type) type;
     102              : }
     103              : 
     104              : /**
     105              :  * @brief Convert the type from tensor_type to ml_tensor_type_e.
     106              :  * @note This code is based on the same order between NNS type and ML type.
     107              :  * The index should be the same in case of adding a new type.
     108              :  */
     109              : static ml_tensor_type_e
     110            0 : convert_ml_tensor_type_from (tensor_type type)
     111              : {
     112            0 :   if (type < _NNS_INT32 || type >= _NNS_END) {
     113            0 :     _ml_error_report
     114              :         ("Failed to convert the type. Input tensor_type %d is invalid.", type);
     115            0 :     return ML_TENSOR_TYPE_UNKNOWN;
     116              :   }
     117              : 
     118            0 :   return (ml_tensor_type_e) type;
     119              : }
     120              : 
     121              : /**
     122              :  * @brief Gets the version string of machine-learning API.
     123              :  */
     124              : char *
     125            0 : ml_api_get_version_string (void)
     126              : {
     127            0 :   return g_strdup_printf ("Machine Learning API %s", VERSION);
     128              : }
     129              : 
     130              : /**
     131              :  * @brief Internal function to create tensors-info handle.
     132              :  */
     133              : static int
     134            2 : _ml_tensors_info_create_internal (ml_tensors_info_h * info, bool extended)
     135              : {
     136              :   ml_tensors_info_s *tensors_info;
     137              : 
     138            2 :   check_feature_state (ML_FEATURE);
     139              : 
     140            2 :   if (!info)
     141            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     142              :         "The parameter, info, is NULL. Provide a valid pointer.");
     143              : 
     144            2 :   *info = tensors_info = g_new0 (ml_tensors_info_s, 1);
     145            2 :   if (tensors_info == NULL)
     146            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     147              :         "Failed to allocate the tensors info handle. Out of memory?");
     148              : 
     149            2 :   g_mutex_init (&tensors_info->lock);
     150            2 :   tensors_info->is_extended = extended;
     151              : 
     152              :   /* init tensors info struct */
     153            2 :   return _ml_tensors_info_initialize (tensors_info);
     154              : }
     155              : 
     156              : /**
     157              :  * @brief Creates new tensors-info handle and copies tensors information.
     158              :  */
     159              : int
     160            0 : _ml_tensors_info_create_from (const ml_tensors_info_h in,
     161              :     ml_tensors_info_h * out)
     162              : {
     163              :   ml_tensors_info_s *_info;
     164              :   int status;
     165              : 
     166            0 :   if (!in || !out)
     167            0 :     return ML_ERROR_INVALID_PARAMETER;
     168              : 
     169            0 :   _info = (ml_tensors_info_s *) in;
     170              : 
     171            0 :   if (_info->is_extended)
     172            0 :     status = ml_tensors_info_create_extended (out);
     173              :   else
     174            0 :     status = ml_tensors_info_create (out);
     175              : 
     176            0 :   if (status == ML_ERROR_NONE)
     177            0 :     status = ml_tensors_info_clone (*out, in);
     178              : 
     179            0 :   return status;
     180              : }
     181              : 
     182              : /**
     183              :  * @brief Allocates a tensors information handle with default value.
     184              :  */
     185              : int
     186            2 : ml_tensors_info_create (ml_tensors_info_h * info)
     187              : {
     188            2 :   return _ml_tensors_info_create_internal (info, false);
     189              : }
     190              : 
     191              : /**
     192              :  * @brief Allocates an extended tensors information handle with default value.
     193              :  */
     194              : int
     195            0 : ml_tensors_info_create_extended (ml_tensors_info_h * info)
     196              : {
     197            0 :   return _ml_tensors_info_create_internal (info, true);
     198              : }
     199              : 
     200              : /**
     201              :  * @brief Frees the given handle of a tensors information.
     202              :  */
     203              : int
     204            2 : ml_tensors_info_destroy (ml_tensors_info_h info)
     205              : {
     206              :   ml_tensors_info_s *tensors_info;
     207              : 
     208            2 :   check_feature_state (ML_FEATURE);
     209              : 
     210            2 :   tensors_info = (ml_tensors_info_s *) info;
     211              : 
     212            2 :   if (!tensors_info)
     213            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     214              :         "The parameter, info, is NULL. Provide a valid pointer.");
     215              : 
     216            2 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     217            2 :   _ml_tensors_info_free (tensors_info);
     218            2 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     219              : 
     220            2 :   g_mutex_clear (&tensors_info->lock);
     221            2 :   g_free (tensors_info);
     222              : 
     223            2 :   return ML_ERROR_NONE;
     224              : }
     225              : 
     226              : /**
     227              :  * @brief Validates the given tensors info is valid.
     228              :  */
     229              : int
     230            0 : ml_tensors_info_validate (const ml_tensors_info_h info, bool *valid)
     231              : {
     232              :   ml_tensors_info_s *tensors_info;
     233              : 
     234            0 :   check_feature_state (ML_FEATURE);
     235              : 
     236            0 :   if (!valid)
     237            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     238              :         "The data-return parameter, valid, is NULL. It should be a pointer pre-allocated by the caller.");
     239              : 
     240            0 :   tensors_info = (ml_tensors_info_s *) info;
     241              : 
     242            0 :   if (!tensors_info)
     243            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     244              :         "The input parameter, tensors_info, is NULL. It should be a valid ml_tensors_info_h, which is usually created by ml_tensors_info_create().");
     245              : 
     246            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     247            0 :   *valid = gst_tensors_info_validate (&tensors_info->info);
     248            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     249              : 
     250            0 :   return ML_ERROR_NONE;
     251              : }
     252              : 
     253              : /**
     254              :  * @brief Compares the given tensors information.
     255              :  */
     256              : int
     257            0 : _ml_tensors_info_compare (const ml_tensors_info_h info1,
     258              :     const ml_tensors_info_h info2, bool *equal)
     259              : {
     260              :   ml_tensors_info_s *i1, *i2;
     261              : 
     262            0 :   check_feature_state (ML_FEATURE);
     263              : 
     264            0 :   if (info1 == NULL)
     265            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     266              :         "The input parameter, info1, should be a valid ml_tensors_info_h handle, which is usually created by ml_tensors_info_create(). However, info1 is NULL.");
     267            0 :   if (info2 == NULL)
     268            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     269              :         "The input parameter, info2, should be a valid ml_tensors_info_h handle, which is usually created by ml_tensors_info_create(). However, info2 is NULL.");
     270            0 :   if (equal == NULL)
     271            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     272              :         "The output parameter, equal, should be a valid pointer allocated by the caller. However, equal is NULL.");
     273              : 
     274            0 :   i1 = (ml_tensors_info_s *) info1;
     275            0 :   G_LOCK_UNLESS_NOLOCK (*i1);
     276            0 :   i2 = (ml_tensors_info_s *) info2;
     277            0 :   G_LOCK_UNLESS_NOLOCK (*i2);
     278              : 
     279            0 :   *equal = gst_tensors_info_is_equal (&i1->info, &i2->info);
     280              : 
     281            0 :   G_UNLOCK_UNLESS_NOLOCK (*i2);
     282            0 :   G_UNLOCK_UNLESS_NOLOCK (*i1);
     283            0 :   return ML_ERROR_NONE;
     284              : }
     285              : 
     286              : /**
     287              :  * @brief Sets the number of tensors with given handle of tensors information.
     288              :  */
     289              : int
     290            2 : ml_tensors_info_set_count (ml_tensors_info_h info, unsigned int count)
     291              : {
     292              :   ml_tensors_info_s *tensors_info;
     293              : 
     294            2 :   check_feature_state (ML_FEATURE);
     295              : 
     296            2 :   if (!info)
     297            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     298              :         "The parameter, info, is NULL. It should be a valid ml_tensors_info_h handle, which is usually created by ml_tensors_info_create().");
     299            2 :   if (count > ML_TENSOR_SIZE_LIMIT || count == 0)
     300            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     301              :         "The parameter, count, is the number of tensors, which should be between 1 and %d. The given count is %u.",
     302              :         ML_TENSOR_SIZE_LIMIT, count);
     303              : 
     304            1 :   tensors_info = (ml_tensors_info_s *) info;
     305              : 
     306              :   /* This is atomic. No need for locks */
     307            1 :   tensors_info->info.num_tensors = count;
     308              : 
     309            1 :   return ML_ERROR_NONE;
     310              : }
     311              : 
     312              : /**
     313              :  * @brief Gets the number of tensors with given handle of tensors information.
     314              :  */
     315              : int
     316            0 : ml_tensors_info_get_count (ml_tensors_info_h info, unsigned int *count)
     317              : {
     318              :   ml_tensors_info_s *tensors_info;
     319              : 
     320            0 :   check_feature_state (ML_FEATURE);
     321              : 
     322            0 :   if (!info)
     323            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     324              :         "The parameter, info, is NULL. It should be a valid ml_tensors_info_h handle, which is usually created by ml_tensors_info_create().");
     325            0 :   if (!count)
     326            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     327              :         "The parameter, count, is NULL. It should be a valid unsigned int * pointer, allocated by the caller.");
     328              : 
     329            0 :   tensors_info = (ml_tensors_info_s *) info;
     330              :   /* This is atomic. No need for locks */
     331            0 :   *count = tensors_info->info.num_tensors;
     332              : 
     333            0 :   return ML_ERROR_NONE;
     334              : }
     335              : 
     336              : /**
     337              :  * @brief Sets the tensor name with given handle of tensors information.
     338              :  */
     339              : int
     340            0 : ml_tensors_info_set_tensor_name (ml_tensors_info_h info,
     341              :     unsigned int index, const char *name)
     342              : {
     343              :   ml_tensors_info_s *tensors_info;
     344              :   GstTensorInfo *_info;
     345              : 
     346            0 :   check_feature_state (ML_FEATURE);
     347              : 
     348            0 :   if (!info)
     349            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     350              :         "The parameter, info, is NULL. It should be a valid ml_tensors_info_h handle, which is usually created by ml_tensors_info_create().");
     351              : 
     352            0 :   tensors_info = (ml_tensors_info_s *) info;
     353            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     354              : 
     355            0 :   if (tensors_info->info.num_tensors <= index) {
     356            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     357            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     358              :         "The number of tensors in 'info' parameter is %u, which is not larger than the given 'index' %u. Thus, we cannot get %u'th tensor from 'info'. Please set the number of tensors of 'info' correctly or check the value of the given 'index'.",
     359              :         tensors_info->info.num_tensors, index, index);
     360              :   }
     361              : 
     362            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     363            0 :   if (!_info) {
     364            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     365            0 :     return ML_ERROR_INVALID_PARAMETER;
     366              :   }
     367              : 
     368            0 :   g_clear_pointer (&_info->name, g_free);
     369            0 :   _info->name = g_strdup (name);
     370              : 
     371            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     372            0 :   return ML_ERROR_NONE;
     373              : }
     374              : 
     375              : /**
     376              :  * @brief Gets the tensor name with given handle of tensors information.
     377              :  */
     378              : int
     379            0 : ml_tensors_info_get_tensor_name (ml_tensors_info_h info,
     380              :     unsigned int index, char **name)
     381              : {
     382              :   ml_tensors_info_s *tensors_info;
     383              :   GstTensorInfo *_info;
     384              : 
     385            0 :   check_feature_state (ML_FEATURE);
     386              : 
     387            0 :   if (!info)
     388            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     389              :         "The parameter, info, is NULL. It should be a valid ml_tensors_info_h handle, which is usually created by ml_tensors_info_create().");
     390            0 :   if (!name)
     391            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     392              :         "The parameter, name, is NULL. It should be a valid char ** pointer, allocated by the caller. E.g., char *name; ml_tensors_info_get_tensor_name (info, index, &name);");
     393              : 
     394            0 :   tensors_info = (ml_tensors_info_s *) info;
     395            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     396              : 
     397            0 :   if (tensors_info->info.num_tensors <= index) {
     398            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     399            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     400              :         "The number of tensors in 'info' parameter is %u, which is not larger than the given 'index' %u. Thus, we cannot get %u'th tensor from 'info'. Please set the number of tensors of 'info' correctly or check the value of the given 'index'.",
     401              :         tensors_info->info.num_tensors, index, index);
     402              :   }
     403              : 
     404            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     405            0 :   if (!_info) {
     406            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     407            0 :     return ML_ERROR_INVALID_PARAMETER;
     408              :   }
     409              : 
     410            0 :   *name = g_strdup (_info->name);
     411              : 
     412            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     413            0 :   return ML_ERROR_NONE;
     414              : }
     415              : 
     416              : /**
     417              :  * @brief Sets the tensor type with given handle of tensors information.
     418              :  */
     419              : int
     420            2 : ml_tensors_info_set_tensor_type (ml_tensors_info_h info,
     421              :     unsigned int index, const ml_tensor_type_e type)
     422              : {
     423              :   ml_tensors_info_s *tensors_info;
     424              :   GstTensorInfo *_info;
     425              : 
     426            2 :   check_feature_state (ML_FEATURE);
     427              : 
     428            2 :   if (!info)
     429            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     430              :         "The parameter, info, is NULL. It should be a valid pointer of ml_tensors_info_h, which is usually created by ml_tensors_info_create().");
     431              : 
     432            2 :   if (type >= ML_TENSOR_TYPE_UNKNOWN || type < 0)
     433            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     434              :         "The parameter, type, ML_TENSOR_TYPE_UNKNOWN or out of bound. The value of type should be between 0 and ML_TENSOR_TYPE_UNKNOWN - 1. type = %d, ML_TENSOR_TYPE_UNKNOWN = %d.",
     435              :         type, ML_TENSOR_TYPE_UNKNOWN);
     436              : 
     437              : #ifndef FLOAT16_SUPPORT
     438            1 :   if (type == ML_TENSOR_TYPE_FLOAT16)
     439            1 :     _ml_error_report_return (ML_ERROR_NOT_SUPPORTED,
     440              :         "Float16 (IEEE 754) is not supported by the machine (or the compiler or your build configuration). You cannot configure ml_tensors_info instance with Float16 type.");
     441              : #endif
     442              :   /** @todo add BFLOAT16 when nnstreamer is ready for it. */
     443              : 
     444            0 :   tensors_info = (ml_tensors_info_s *) info;
     445            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     446              : 
     447            0 :   if (tensors_info->info.num_tensors <= index) {
     448            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     449            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     450              :         "The number of tensors in 'info' parameter is %u, which is not larger than the given 'index' %u. Thus, we cannot get %u'th tensor from 'info'. Please set the number of tensors of 'info' correctly or check the value of the given 'index'.",
     451              :         tensors_info->info.num_tensors, index, index);
     452              :   }
     453              : 
     454            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     455            0 :   if (!_info) {
     456            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     457            0 :     return ML_ERROR_INVALID_PARAMETER;
     458              :   }
     459              : 
     460            0 :   _info->type = convert_tensor_type_from (type);
     461              : 
     462            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     463            0 :   return ML_ERROR_NONE;
     464              : }
     465              : 
     466              : /**
     467              :  * @brief Gets the tensor type with given handle of tensors information.
     468              :  */
     469              : int
     470            0 : ml_tensors_info_get_tensor_type (ml_tensors_info_h info,
     471              :     unsigned int index, ml_tensor_type_e * type)
     472              : {
     473              :   ml_tensors_info_s *tensors_info;
     474              :   GstTensorInfo *_info;
     475              : 
     476            0 :   check_feature_state (ML_FEATURE);
     477              : 
     478            0 :   if (!info)
     479            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     480              :         "The parameter, info, is NULL. It should be a valid ml_tensors_info_h handle, which is usually created by ml_tensors_info_create().");
     481            0 :   if (!type)
     482            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     483              :         "The parameter, type, is NULL. It should be a valid pointer of ml_tensor_type_e *, allocated by the caller. E.g., ml_tensor_type_e t; ml_tensors_info_get_tensor_type (info, index, &t);");
     484              : 
     485            0 :   tensors_info = (ml_tensors_info_s *) info;
     486            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     487              : 
     488            0 :   if (tensors_info->info.num_tensors <= index) {
     489            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     490            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     491              :         "The number of tensors in 'info' parameter is %u, which is not larger than the given 'index' %u. Thus, we cannot get %u'th tensor from 'info'. Please set the number of tensors of 'info' correctly or check the value of the given 'index'.",
     492              :         tensors_info->info.num_tensors, index, index);
     493              :   }
     494              : 
     495            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     496            0 :   if (!_info) {
     497            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     498            0 :     return ML_ERROR_INVALID_PARAMETER;
     499              :   }
     500              : 
     501            0 :   *type = convert_ml_tensor_type_from (_info->type);
     502              : 
     503            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     504            0 :   return ML_ERROR_NONE;
     505              : }
     506              : 
     507              : /**
     508              :  * @brief Sets the tensor dimension with given handle of tensors information.
     509              :  */
     510              : int
     511            0 : ml_tensors_info_set_tensor_dimension (ml_tensors_info_h info,
     512              :     unsigned int index, const ml_tensor_dimension dimension)
     513              : {
     514              :   ml_tensors_info_s *tensors_info;
     515              :   GstTensorInfo *_info;
     516              :   guint i, rank, max_rank;
     517              : 
     518            0 :   check_feature_state (ML_FEATURE);
     519              : 
     520            0 :   if (!info)
     521            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     522              :         "The parameter, info, is NULL. It should be a valid pointer of ml_tensors_info_h, which is usually created by ml_tensors_info_create().");
     523              : 
     524            0 :   tensors_info = (ml_tensors_info_s *) info;
     525            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     526              : 
     527            0 :   if (tensors_info->info.num_tensors <= index) {
     528            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     529            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     530              :         "The number of tensors in 'info' parameter is %u, which is not larger than the given 'index' %u. Thus, we cannot get %u'th tensor from 'info'. Please set the number of tensors of 'info' correctly or check the value of the given 'index'.",
     531              :         tensors_info->info.num_tensors, index, index);
     532              :   }
     533              : 
     534              :   /**
     535              :    * Validate dimension.
     536              :    * We cannot use util function to get the rank of tensor dimension here.
     537              :    * The old rank limit is 4, and testcases or app may set old dimension.
     538              :    */
     539            0 :   max_rank = tensors_info->is_extended ?
     540            0 :       ML_TENSOR_RANK_LIMIT : ML_TENSOR_RANK_LIMIT_PREV;
     541            0 :   rank = max_rank + 1;
     542            0 :   for (i = 0; i < max_rank; i++) {
     543            0 :     if (dimension[i] == 0) {
     544            0 :       if (rank > max_rank)
     545            0 :         rank = i;
     546              :     }
     547              : 
     548            0 :     if (rank == 0 || (i > rank && dimension[i] > 0)) {
     549            0 :       G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     550            0 :       _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     551              :           "The parameter, dimension, is invalid. It should be a valid unsigned integer array.");
     552              :     }
     553              :   }
     554              : 
     555            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     556            0 :   if (!_info) {
     557            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     558            0 :     return ML_ERROR_INVALID_PARAMETER;
     559              :   }
     560              : 
     561            0 :   for (i = 0; i < ML_TENSOR_RANK_LIMIT_PREV; i++) {
     562            0 :     _info->dimension[i] = dimension[i];
     563              :   }
     564              : 
     565            0 :   for (i = ML_TENSOR_RANK_LIMIT_PREV; i < ML_TENSOR_RANK_LIMIT; i++) {
     566            0 :     _info->dimension[i] = (tensors_info->is_extended ? dimension[i] : 0);
     567              :   }
     568              : 
     569            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     570            0 :   return ML_ERROR_NONE;
     571              : }
     572              : 
     573              : /**
     574              :  * @brief Gets the tensor dimension with given handle of tensors information.
     575              :  */
     576              : int
     577            0 : ml_tensors_info_get_tensor_dimension (ml_tensors_info_h info,
     578              :     unsigned int index, ml_tensor_dimension dimension)
     579              : {
     580              :   ml_tensors_info_s *tensors_info;
     581              :   GstTensorInfo *_info;
     582            0 :   guint i, valid_rank = ML_TENSOR_RANK_LIMIT;
     583              : 
     584            0 :   check_feature_state (ML_FEATURE);
     585              : 
     586            0 :   if (!info)
     587            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     588              :         "The parameter, info, is NULL. It should be a valid pointer of ml_tensors_info_h, which is usually created by ml_tensors_info_create().");
     589              : 
     590            0 :   tensors_info = (ml_tensors_info_s *) info;
     591            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     592              : 
     593            0 :   if (tensors_info->info.num_tensors <= index) {
     594            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     595            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     596              :         "The number of tensors in 'info' parameter is %u, which is not larger than the given 'index' %u. Thus, we cannot get %u'th tensor from 'info'. Please set the number of tensors of 'info' correctly or check the value of the given 'index'.",
     597              :         tensors_info->info.num_tensors, index, index);
     598              :   }
     599              : 
     600            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     601            0 :   if (!_info) {
     602            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     603            0 :     return ML_ERROR_INVALID_PARAMETER;
     604              :   }
     605              : 
     606            0 :   if (!tensors_info->is_extended)
     607            0 :     valid_rank = ML_TENSOR_RANK_LIMIT_PREV;
     608              : 
     609            0 :   for (i = 0; i < valid_rank; i++) {
     610            0 :     dimension[i] = _info->dimension[i];
     611              :   }
     612              : 
     613            0 :   for (; i < ML_TENSOR_RANK_LIMIT; i++)
     614            0 :     dimension[i] = 0;
     615              : 
     616            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     617            0 :   return ML_ERROR_NONE;
     618              : }
     619              : 
     620              : /**
     621              :  * @brief Gets the byte size of the given handle of tensors information.
     622              :  */
     623              : int
     624            0 : ml_tensors_info_get_tensor_size (ml_tensors_info_h info,
     625              :     int index, size_t *data_size)
     626              : {
     627              :   ml_tensors_info_s *tensors_info;
     628              : 
     629            0 :   check_feature_state (ML_FEATURE);
     630              : 
     631            0 :   if (!info)
     632            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     633              :         "The parameter, info, is NULL. Provide a valid pointer.");
     634            0 :   if (!data_size)
     635            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     636              :         "The parameter, data_size, is NULL. It should be a valid size_t * pointer allocated by the caller. E.g., size_t d; ml_tensors_info_get_tensor_size (info, index, &d);");
     637              : 
     638            0 :   tensors_info = (ml_tensors_info_s *) info;
     639            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     640              : 
     641              :   /* init 0 */
     642            0 :   *data_size = 0;
     643              : 
     644            0 :   if (index >= 0 && tensors_info->info.num_tensors <= index) {
     645            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     646            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     647              :         "The number of tensors in 'info' parameter is %u, which is not larger than the given 'index' %u. Thus, we cannot get %u'th tensor from 'info'. Please set the number of tensors of 'info' correctly or check the value of the given 'index'.",
     648              :         tensors_info->info.num_tensors, index, index);
     649              :   }
     650              : 
     651            0 :   *data_size = gst_tensors_info_get_size (&tensors_info->info, index);
     652              : 
     653            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     654            0 :   return ML_ERROR_NONE;
     655              : }
     656              : 
     657              : /**
     658              :  * @brief Initializes the tensors information with default value.
     659              :  */
     660              : int
     661            2 : _ml_tensors_info_initialize (ml_tensors_info_s * info)
     662              : {
     663            2 :   if (!info)
     664            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     665              :         "The parameter, info, is NULL. Provide a valid pointer.");
     666              : 
     667            2 :   gst_tensors_info_init (&info->info);
     668              : 
     669            2 :   return ML_ERROR_NONE;
     670              : }
     671              : 
     672              : /**
     673              :  * @brief Frees and initialize the data in tensors info.
     674              :  * @note This does not touch the lock. The caller should lock.
     675              :  */
     676              : void
     677            2 : _ml_tensors_info_free (ml_tensors_info_s * info)
     678              : {
     679            2 :   if (!info)
     680            0 :     return;
     681              : 
     682            2 :   gst_tensors_info_free (&info->info);
     683              : }
     684              : 
     685              : /**
     686              :  * @brief Frees the tensors data handle and its data.
     687              :  * @param[in] data The handle of tensors data.
     688              :  * @param[in] free_data The flag to free the buffers in handle.
     689              :  * @return @c 0 on success. Otherwise a negative error value.
     690              :  */
     691              : int
     692            0 : _ml_tensors_data_destroy_internal (ml_tensors_data_h data, gboolean free_data)
     693              : {
     694            0 :   int status = ML_ERROR_NONE;
     695              :   ml_tensors_data_s *_data;
     696              :   guint i;
     697              : 
     698            0 :   if (data == NULL)
     699            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     700              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     701              : 
     702            0 :   _data = (ml_tensors_data_s *) data;
     703            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
     704              : 
     705            0 :   if (free_data) {
     706            0 :     if (_data->destroy) {
     707            0 :       status = _data->destroy (_data, _data->user_data);
     708            0 :       if (status != ML_ERROR_NONE) {
     709            0 :         G_UNLOCK_UNLESS_NOLOCK (*_data);
     710            0 :         _ml_error_report_return_continue (status,
     711              :             "Tried to destroy internal user_data of the given parameter, data, with its destroy callback; however, it has failed with %d.",
     712              :             status);
     713              :       }
     714              :     } else {
     715            0 :       for (i = 0; i < _data->num_tensors; i++) {
     716            0 :         g_clear_pointer (&_data->tensors[i].data, g_free);
     717              :       }
     718              :     }
     719              :   }
     720              : 
     721            0 :   if (_data->info)
     722            0 :     ml_tensors_info_destroy (_data->info);
     723              : 
     724            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     725            0 :   g_mutex_clear (&_data->lock);
     726            0 :   g_free (_data);
     727            0 :   return status;
     728              : }
     729              : 
     730              : /**
     731              :  * @brief Frees the tensors data pointer.
     732              :  * @note This does not touch the lock
     733              :  */
     734              : int
     735            0 : ml_tensors_data_destroy (ml_tensors_data_h data)
     736              : {
     737              :   int ret;
     738            0 :   check_feature_state (ML_FEATURE);
     739            0 :   ret = _ml_tensors_data_destroy_internal (data, TRUE);
     740            0 :   if (ret != ML_ERROR_NONE)
     741            0 :     _ml_error_report_return_continue (ret,
     742              :         "Call to _ml_tensors_data_destroy_internal failed with %d", ret);
     743            0 :   return ret;
     744              : }
     745              : 
     746              : /**
     747              :  * @brief Creates a tensor data frame without buffer with the given tensors information.
     748              :  * @note Memory for tensor data buffers is not allocated.
     749              :  */
     750              : int
     751            0 : _ml_tensors_data_create_no_alloc (const ml_tensors_info_h info,
     752              :     ml_tensors_data_h * data)
     753              : {
     754              :   ml_tensors_data_s *_data;
     755              :   ml_tensors_info_s *_info;
     756              :   guint i;
     757            0 :   int status = ML_ERROR_NONE;
     758              : 
     759            0 :   check_feature_state (ML_FEATURE);
     760              : 
     761            0 :   if (data == NULL)
     762            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     763              :         "The parameter, data, is NULL. It should be a valid ml_tensors_info_h handle that may hold a space for ml_tensors_info_h. E.g., ml_tensors_data_h data; _ml_tensors_data_create_no_alloc (info, &data);.");
     764              : 
     765              :   /* init null */
     766            0 :   *data = NULL;
     767              : 
     768            0 :   _data = g_new0 (ml_tensors_data_s, 1);
     769            0 :   if (!_data)
     770            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     771              :         "Failed to allocate memory for tensors data. Probably the system is out of memory.");
     772              : 
     773            0 :   g_mutex_init (&_data->lock);
     774              : 
     775              :   /**
     776              :    * We now release allocated data only when _ml_tensors_data_destroy_internal() is called.
     777              :    * Be careful, if you update the number of tensors after creating the data handle,
     778              :    * you should manage the memories with changed index.
     779              :    */
     780            0 :   _info = (ml_tensors_info_s *) info;
     781            0 :   if (_info != NULL) {
     782            0 :     status = _ml_tensors_info_create_from (info, &_data->info);
     783            0 :     if (status != ML_ERROR_NONE) {
     784            0 :       _ml_error_report_continue
     785              :           ("Failed to create internal information handle for tensors data.");
     786            0 :       goto error;
     787              :     }
     788              : 
     789            0 :     G_LOCK_UNLESS_NOLOCK (*_info);
     790            0 :     _data->num_tensors = _info->info.num_tensors;
     791            0 :     for (i = 0; i < _data->num_tensors; i++) {
     792            0 :       _data->tensors[i].size = gst_tensors_info_get_size (&_info->info, i);
     793            0 :       _data->tensors[i].data = NULL;
     794              :     }
     795            0 :     G_UNLOCK_UNLESS_NOLOCK (*_info);
     796              :   }
     797              : 
     798            0 : error:
     799            0 :   if (status == ML_ERROR_NONE) {
     800            0 :     *data = _data;
     801              :   } else {
     802            0 :     _ml_tensors_data_destroy_internal (_data, FALSE);
     803              :   }
     804              : 
     805            0 :   return status;
     806              : }
     807              : 
     808              : /**
     809              :  * @brief Clones the given tensor data frame from the given tensors data. (more info in nnstreamer.h)
     810              :  * @note Memory ptr for data buffer is copied. No new memory for data buffer is allocated.
     811              :  */
     812              : int
     813            0 : _ml_tensors_data_clone_no_alloc (const ml_tensors_data_s * data_src,
     814              :     ml_tensors_data_h * data)
     815              : {
     816              :   int status;
     817              :   ml_tensors_data_s *_data;
     818              : 
     819            0 :   check_feature_state (ML_FEATURE);
     820              : 
     821            0 :   if (data == NULL)
     822            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     823              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     824            0 :   if (data_src == NULL)
     825            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     826              :         "The parameter, data_src, the source data to be cloned, is NULL. It should be a valid ml_tensors_data_s struct (internal representation of ml_tensors_data_h handle).");
     827              : 
     828            0 :   status = _ml_tensors_data_create_no_alloc (data_src->info,
     829              :       (ml_tensors_data_h *) & _data);
     830            0 :   if (status != ML_ERROR_NONE)
     831            0 :     _ml_error_report_return_continue (status,
     832              :         "The call to _ml_tensors_data_create_no_alloc has failed with %d.",
     833              :         status);
     834              : 
     835            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
     836              : 
     837            0 :   _data->num_tensors = data_src->num_tensors;
     838            0 :   memcpy (_data->tensors, data_src->tensors,
     839            0 :       sizeof (GstTensorMemory) * data_src->num_tensors);
     840              : 
     841            0 :   *data = _data;
     842            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     843            0 :   return ML_ERROR_NONE;
     844              : }
     845              : 
     846              : /**
     847              :  * @brief  Allocates zero-initialized memory of the given size for the tensor at the specified index
     848              :  * in the tensor data structure, and sets the size value for that tensor.
     849              :  */
     850              : static int
     851            0 : _ml_tensor_data_alloc (ml_tensors_data_s * data, guint index, const size_t size)
     852              : {
     853            0 :   if (!data || index >= data->num_tensors || size <= 0)
     854            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     855              :         "Invalid parameter: data is invalid, or index is out of range.");
     856              : 
     857            0 :   data->tensors[index].size = size;
     858            0 :   data->tensors[index].data = g_malloc0 (size);
     859            0 :   if (data->tensors[index].data == NULL)
     860            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     861              :         "Failed to allocate memory for tensor data.");
     862              : 
     863            0 :   return ML_ERROR_NONE;
     864              : }
     865              : 
     866              : /**
     867              :  * @brief Copies the tensor data frame.
     868              :  */
     869              : int
     870            0 : ml_tensors_data_clone (const ml_tensors_data_h in, ml_tensors_data_h * out)
     871              : {
     872              :   int status;
     873              :   unsigned int i;
     874            0 :   ml_tensors_data_s *_in, *_out = NULL;
     875              : 
     876            0 :   check_feature_state (ML_FEATURE);
     877              : 
     878            0 :   if (in == NULL)
     879            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     880              :         "The parameter, in, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     881              : 
     882            0 :   if (out == NULL)
     883            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     884              :         "The parameter, out, is NULL. It should be a valid pointer to a space that can hold a ml_tensors_data_h handle. E.g., ml_tensors_data_h out; ml_tensors_data_clone (in, &out);.");
     885              : 
     886            0 :   _in = (ml_tensors_data_s *) in;
     887            0 :   G_LOCK_UNLESS_NOLOCK (*_in);
     888              : 
     889            0 :   status = ml_tensors_data_create (_in->info, out);
     890            0 :   if (status != ML_ERROR_NONE) {
     891            0 :     _ml_loge ("Failed to create new handle to copy tensor data.");
     892            0 :     goto error;
     893              :   }
     894              : 
     895            0 :   _out = (ml_tensors_data_s *) (*out);
     896              : 
     897            0 :   for (i = 0; i < _out->num_tensors; ++i) {
     898            0 :     if (!_out->tensors[i].data) {
     899              :       /**
     900              :        * If tensor format is static, memory is already allocated.
     901              :        * However, flexible tensor is not. To copy raw data, allocate new memory here.
     902              :        */
     903            0 :       status = _ml_tensor_data_alloc (_out, i, _in->tensors[i].size);
     904            0 :       if (status != ML_ERROR_NONE) {
     905            0 :         goto error;
     906              :       }
     907              :     }
     908              : 
     909            0 :     memcpy (_out->tensors[i].data, _in->tensors[i].data, _in->tensors[i].size);
     910              :   }
     911              : 
     912            0 : error:
     913            0 :   if (status != ML_ERROR_NONE) {
     914              :     /* Failed to create new data handle. */
     915            0 :     _ml_tensors_data_destroy_internal (_out, TRUE);
     916            0 :     *out = NULL;
     917              :   }
     918              : 
     919            0 :   G_UNLOCK_UNLESS_NOLOCK (*_in);
     920            0 :   return status;
     921              : }
     922              : 
     923              : /**
     924              :  * @brief Gets the tensors information of given tensor data frame.
     925              :  */
     926              : int
     927            0 : ml_tensors_data_get_info (const ml_tensors_data_h data,
     928              :     ml_tensors_info_h * info)
     929              : {
     930              :   int status;
     931              :   ml_tensors_data_s *_data;
     932              : 
     933            0 :   check_feature_state (ML_FEATURE);
     934              : 
     935            0 :   if (data == NULL) {
     936            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     937              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     938              :   }
     939              : 
     940            0 :   if (info == NULL) {
     941            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     942              :         "The parameter, info, is NULL. It should be a valid pointer to a space that can hold a ml_tensors_info_h handle. E.g., ml_tensors_info_h info; ml_tensors_data_get_info (data, &info);.");
     943              :   }
     944              : 
     945            0 :   _data = (ml_tensors_data_s *) data;
     946            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
     947              : 
     948            0 :   status = _ml_tensors_info_create_from (_data->info, info);
     949            0 :   if (status != ML_ERROR_NONE) {
     950            0 :     _ml_error_report_continue
     951              :         ("Failed to get the tensor information from data handle.");
     952              :   }
     953              : 
     954            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     955            0 :   return status;
     956              : }
     957              : 
     958              : /**
     959              :  * @brief Allocates a tensor data frame with the given tensors info. (more info in nnstreamer.h)
     960              :  */
     961              : int
     962            0 : ml_tensors_data_create (const ml_tensors_info_h info, ml_tensors_data_h * data)
     963              : {
     964            0 :   int status = ML_ERROR_NONE;
     965            0 :   ml_tensors_info_s *_info = NULL;
     966            0 :   ml_tensors_data_s *_data = NULL;
     967              :   guint i;
     968              :   bool valid;
     969              : 
     970            0 :   check_feature_state (ML_FEATURE);
     971              : 
     972            0 :   if (info == NULL)
     973            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     974              :         "The parameter, info, is NULL. It should be a valid pointer of ml_tensors_info_h, which is usually created by ml_tensors_info_create().");
     975            0 :   if (data == NULL)
     976            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     977              :         "The parameter, data, is NULL. It should be a valid space to hold a ml_tensors_data_h handle. E.g., ml_tensors_data_h data; ml_tensors_data_create (info, &data);.");
     978              : 
     979            0 :   status = ml_tensors_info_validate (info, &valid);
     980            0 :   if (status != ML_ERROR_NONE)
     981            0 :     _ml_error_report_return_continue (status,
     982              :         "ml_tensors_info_validate() has reported that the parameter, info, is not NULL, but its contents are not valid. The user must provide a valid tensor information with it.");
     983            0 :   if (!valid)
     984            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     985              :         "The parameter, info, is not NULL, but its contents are not valid. The user must provide a valid tensor information with it. Probably, there is an entry that is not allocated or dimension/type information not available. The given info should have valid number of tensors, entries of every tensor along with its type and dimension info.");
     986              : 
     987              :   status =
     988            0 :       _ml_tensors_data_create_no_alloc (info, (ml_tensors_data_h *) & _data);
     989              : 
     990            0 :   if (status != ML_ERROR_NONE) {
     991            0 :     _ml_error_report_return_continue (status,
     992              :         "Failed to allocate tensor data based on the given info with the call to _ml_tensors_data_create_no_alloc (): %d. Check if it's out-of-memory.",
     993              :         status);
     994              :   }
     995              : 
     996            0 :   _info = (ml_tensors_info_s *) info;
     997            0 :   if (_info->info.format == _NNS_TENSOR_FORMAT_STATIC) {
     998            0 :     for (i = 0; i < _data->num_tensors; i++) {
     999            0 :       status = _ml_tensor_data_alloc (_data, i, _data->tensors[i].size);
    1000            0 :       if (status != ML_ERROR_NONE)
    1001            0 :         goto error;
    1002              :     }
    1003              :   } else {
    1004            0 :     _ml_logw
    1005              :         ("[ml_tensors_data_create] format is not static, skipping tensor memory allocation. Use ml_tensors_data_set_tensor_data() to update data buffer.");
    1006              :   }
    1007              : 
    1008            0 : error:
    1009            0 :   if (status == ML_ERROR_NONE) {
    1010            0 :     *data = _data;
    1011              :   } else {
    1012            0 :     _ml_tensors_data_destroy_internal (_data, TRUE);
    1013              :   }
    1014              : 
    1015            0 :   return status;
    1016              : }
    1017              : 
    1018              : /**
    1019              :  * @brief Gets a tensor data of given handle.
    1020              :  */
    1021              : int
    1022            0 : ml_tensors_data_get_tensor_data (ml_tensors_data_h data, unsigned int index,
    1023              :     void **raw_data, size_t *data_size)
    1024              : {
    1025              :   ml_tensors_data_s *_data;
    1026            0 :   int status = ML_ERROR_NONE;
    1027              : 
    1028            0 :   check_feature_state (ML_FEATURE);
    1029              : 
    1030            0 :   if (data == NULL)
    1031            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1032              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
    1033            0 :   if (raw_data == NULL)
    1034            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1035              :         "The parameter, raw_data, is NULL. It should be a valid, non-NULL, void ** pointer, which is supposed to point to the raw data of tensors[index] after the call.");
    1036            0 :   if (data_size == NULL)
    1037            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1038              :         "The parameter, data_size, is NULL. It should be a valid, non-NULL, size_t * pointer, which is supposed to point to the size of returning raw_data after the call.");
    1039              : 
    1040            0 :   _data = (ml_tensors_data_s *) data;
    1041            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
    1042              : 
    1043            0 :   if (_data->num_tensors <= index) {
    1044            0 :     _ml_error_report
    1045              :         ("The parameter, index, is out of bound. The number of tensors of 'data' is %u while you requested %u'th tensor (index = %u).",
    1046              :         _data->num_tensors, index, index);
    1047            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1048            0 :     goto report;
    1049              :   }
    1050              : 
    1051            0 :   *raw_data = _data->tensors[index].data;
    1052            0 :   *data_size = _data->tensors[index].size;
    1053              : 
    1054            0 : report:
    1055            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1056            0 :   return status;
    1057              : }
    1058              : 
    1059              : /**
    1060              :  * @brief Copies a tensor data to given handle.
    1061              :  */
    1062              : int
    1063            0 : ml_tensors_data_set_tensor_data (ml_tensors_data_h data, unsigned int index,
    1064              :     const void *raw_data, const size_t data_size)
    1065              : {
    1066            0 :   ml_tensors_info_s *_info = NULL;
    1067              :   ml_tensors_data_s *_data;
    1068            0 :   int status = ML_ERROR_NONE;
    1069              : 
    1070            0 :   check_feature_state (ML_FEATURE);
    1071              : 
    1072            0 :   if (data == NULL)
    1073            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1074              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
    1075            0 :   if (raw_data == NULL)
    1076            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1077              :         "The parameter, raw_data, is NULL. It should be a valid, non-NULL, void * pointer, which is supposed to point to the raw data of tensors[index: %u].",
    1078              :         index);
    1079              : 
    1080            0 :   _data = (ml_tensors_data_s *) data;
    1081            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
    1082              : 
    1083            0 :   if (_data->num_tensors <= index) {
    1084            0 :     _ml_error_report
    1085              :         ("The parameter, index, is out of bound. The number of tensors of 'data' is %u, while you've requested index of %u.",
    1086              :         _data->num_tensors, index);
    1087            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1088            0 :     goto report;
    1089              :   }
    1090              : 
    1091              :   /**
    1092              :    * By default, the tensor format is _NNS_TENSOR_FORMAT_STATIC.
    1093              :    * In this case, memory allocation and the setting of _data->tensors[index].size
    1094              :    * are already handled in ml_tensors_data_create().
    1095              :    * So for the STATIC format, both the `size` and `data` pointer should already be valid here.
    1096              :    *
    1097              :    * For FLEXIBLE format, memory may not be allocated yet and will be handled here.
    1098              :    */
    1099            0 :   _info = (ml_tensors_info_s *) _data->info;
    1100            0 :   if (_info && _info->info.format != _NNS_TENSOR_FORMAT_STATIC) {
    1101            0 :     if (!_data->tensors[index].data ||
    1102            0 :         _data->tensors[index].size != data_size) {
    1103            0 :       _ml_logw
    1104              :           ("Memory allocation was not performed in ml_tensor_data_create() when tensor format is flexible.");
    1105              : 
    1106            0 :       g_clear_pointer (&_data->tensors[index].data, g_free);
    1107              : 
    1108            0 :       status = _ml_tensor_data_alloc (_data, index, data_size);
    1109            0 :       if (status != ML_ERROR_NONE) {
    1110            0 :         goto report;
    1111              :       }
    1112              :     }
    1113              :   }
    1114              : 
    1115            0 :   if (data_size <= 0 || _data->tensors[index].size < data_size) {
    1116            0 :     _ml_error_report
    1117              :         ("The parameter, data_size (%zu), is invalid. It should be larger than 0 and not larger than the required size of tensors[index: %u] (%zu).",
    1118              :         data_size, index, _data->tensors[index].size);
    1119            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1120            0 :     goto report;
    1121              :   }
    1122              : 
    1123            0 :   if (_data->tensors[index].data != raw_data)
    1124            0 :     memcpy (_data->tensors[index].data, raw_data, data_size);
    1125              : 
    1126            0 : report:
    1127            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1128            0 :   return status;
    1129              : }
    1130              : 
    1131              : /**
    1132              :  * @brief Copies tensor meta info.
    1133              :  */
    1134              : int
    1135            0 : ml_tensors_info_clone (ml_tensors_info_h dest, const ml_tensors_info_h src)
    1136              : {
    1137              :   ml_tensors_info_s *dest_info, *src_info;
    1138            0 :   int status = ML_ERROR_NONE;
    1139              : 
    1140            0 :   check_feature_state (ML_FEATURE);
    1141              : 
    1142            0 :   dest_info = (ml_tensors_info_s *) dest;
    1143            0 :   src_info = (ml_tensors_info_s *) src;
    1144              : 
    1145            0 :   if (!dest_info)
    1146            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1147              :         "The parameter, dest, is NULL. It should be an allocated handle (ml_tensors_info_h), usually allocated by ml_tensors_info_create ().");
    1148            0 :   if (!src_info)
    1149            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1150              :         "The parameter, src, is NULL. It should be a handle (ml_tensors_info_h) with valid data.");
    1151              : 
    1152            0 :   G_LOCK_UNLESS_NOLOCK (*dest_info);
    1153            0 :   G_LOCK_UNLESS_NOLOCK (*src_info);
    1154              : 
    1155            0 :   if (gst_tensors_info_validate (&src_info->info)) {
    1156            0 :     dest_info->is_extended = src_info->is_extended;
    1157            0 :     gst_tensors_info_copy (&dest_info->info, &src_info->info);
    1158              :   } else {
    1159            0 :     _ml_error_report
    1160              :         ("The parameter, src, is a ml_tensors_info_h handle without valid data. Every tensor-info of tensors-info should have a valid type and dimension information and the number of tensors should be between 1 and %d.",
    1161              :         ML_TENSOR_SIZE_LIMIT);
    1162            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1163              :   }
    1164              : 
    1165            0 :   G_UNLOCK_UNLESS_NOLOCK (*src_info);
    1166            0 :   G_UNLOCK_UNLESS_NOLOCK (*dest_info);
    1167              : 
    1168            0 :   return status;
    1169              : }
    1170              : 
    1171              : /**
    1172              :  * @brief Replaces string.
    1173              :  * This function deallocates the input source string.
    1174              :  * This is copied from nnstreamer/tensor_common.c by the nnstreamer maintainer.
    1175              :  * @param[in] source The input string. This will be freed when returning the replaced string.
    1176              :  * @param[in] what The string to search for.
    1177              :  * @param[in] to The string to be replaced.
    1178              :  * @param[in] delimiters The characters which specify the place to split the string. Set NULL to replace all matched string.
    1179              :  * @param[out] count The count of replaced. Set NULL if it is unnecessary.
    1180              :  * @return Newly allocated string. The returned string should be freed with g_free().
    1181              :  */
    1182              : gchar *
    1183            0 : _ml_replace_string (gchar * source, const gchar * what, const gchar * to,
    1184              :     const gchar * delimiters, guint * count)
    1185              : {
    1186              :   GString *builder;
    1187              :   gchar *start, *pos, *result;
    1188            0 :   guint changed = 0;
    1189              :   gsize len;
    1190              : 
    1191            0 :   g_return_val_if_fail (source, NULL);
    1192            0 :   g_return_val_if_fail (what && to, source);
    1193              : 
    1194            0 :   len = strlen (what);
    1195            0 :   start = source;
    1196              : 
    1197            0 :   builder = g_string_new (NULL);
    1198            0 :   while ((pos = g_strstr_len (start, -1, what)) != NULL) {
    1199            0 :     gboolean skip = FALSE;
    1200              : 
    1201            0 :     if (delimiters) {
    1202              :       const gchar *s;
    1203              :       gchar *prev, *next;
    1204              :       gboolean prev_split, next_split;
    1205              : 
    1206            0 :       prev = next = NULL;
    1207            0 :       prev_split = next_split = FALSE;
    1208              : 
    1209            0 :       if (pos != source)
    1210            0 :         prev = pos - 1;
    1211            0 :       if (*(pos + len) != '\0')
    1212            0 :         next = pos + len;
    1213              : 
    1214            0 :       for (s = delimiters; *s != '\0'; ++s) {
    1215            0 :         if (!prev || *s == *prev)
    1216            0 :           prev_split = TRUE;
    1217            0 :         if (!next || *s == *next)
    1218            0 :           next_split = TRUE;
    1219            0 :         if (prev_split && next_split)
    1220            0 :           break;
    1221              :       }
    1222              : 
    1223            0 :       if (!prev_split || !next_split)
    1224            0 :         skip = TRUE;
    1225              :     }
    1226              : 
    1227            0 :     builder = g_string_append_len (builder, start, pos - start);
    1228              : 
    1229              :     /* replace string if found */
    1230            0 :     if (skip)
    1231            0 :       builder = g_string_append_len (builder, pos, len);
    1232              :     else
    1233            0 :       builder = g_string_append (builder, to);
    1234              : 
    1235            0 :     start = pos + len;
    1236            0 :     if (!skip)
    1237            0 :       changed++;
    1238              :   }
    1239              : 
    1240              :   /* append remains */
    1241            0 :   builder = g_string_append (builder, start);
    1242            0 :   result = g_string_free (builder, FALSE);
    1243              : 
    1244            0 :   if (count)
    1245            0 :     *count = changed;
    1246              : 
    1247            0 :   g_free (source);
    1248            0 :   return result;
    1249              : }
    1250              : 
    1251              : /**
    1252              :  * @brief Converts predefined entity.
    1253              :  */
    1254              : gchar *
    1255            0 : _ml_convert_predefined_entity (const gchar * str)
    1256              : {
    1257            0 :   gchar *converted = g_strdup (str);
    1258              : 
    1259              : #if defined(__ANDROID__)
    1260              :   {
    1261              :     extern const char *nnstreamer_native_get_data_path (void);
    1262              : 
    1263              :     const char *data_path = nnstreamer_native_get_data_path ();
    1264              : 
    1265              :     converted = _ml_replace_string (converted, "@APP_DATA_PATH@", data_path,
    1266              :         NULL, NULL);
    1267              :   }
    1268              : #endif
    1269              : 
    1270            0 :   return converted;
    1271              : }
    1272              : 
    1273              : /**
    1274              :  * @brief error reporting infra
    1275              :  */
    1276              : #define _ML_ERRORMSG_LENGTH (4096U)
    1277              : static char errormsg[_ML_ERRORMSG_LENGTH] = { 0 };      /* one page limit */
    1278              : 
    1279              : static int reported = 0;
    1280              : G_LOCK_DEFINE_STATIC (errlock);
    1281              : 
    1282              : /**
    1283              :  * @brief public API function of error reporting.
    1284              :  */
    1285              : const char *
    1286            0 : ml_error (void)
    1287              : {
    1288            0 :   G_LOCK (errlock);
    1289            0 :   if (reported != 0) {
    1290            0 :     errormsg[0] = '\0';
    1291            0 :     reported = 0;
    1292              :   }
    1293            0 :   if (errormsg[0] == '\0') {
    1294            0 :     G_UNLOCK (errlock);
    1295            0 :     return NULL;
    1296              :   }
    1297              : 
    1298            0 :   reported = 1;
    1299              : 
    1300            0 :   G_UNLOCK (errlock);
    1301            0 :   return errormsg;
    1302              : }
    1303              : 
    1304              : /**
    1305              :  * @brief Internal interface to write messages for ml_error()
    1306              :  */
    1307              : void
    1308            3 : _ml_error_report_ (const char *fmt, ...)
    1309              : {
    1310              :   int n;
    1311              :   va_list arg_ptr;
    1312            3 :   G_LOCK (errlock);
    1313              : 
    1314            3 :   va_start (arg_ptr, fmt);
    1315            3 :   n = vsnprintf (errormsg, _ML_ERRORMSG_LENGTH, fmt, arg_ptr);
    1316            3 :   va_end (arg_ptr);
    1317              : 
    1318            3 :   if (n > _ML_ERRORMSG_LENGTH) {
    1319            0 :     errormsg[_ML_ERRORMSG_LENGTH - 2] = '.';
    1320            0 :     errormsg[_ML_ERRORMSG_LENGTH - 3] = '.';
    1321            0 :     errormsg[_ML_ERRORMSG_LENGTH - 4] = '.';
    1322              :   }
    1323              : 
    1324            3 :   _ml_loge ("%s", errormsg);
    1325              : 
    1326            3 :   reported = 0;
    1327              : 
    1328            3 :   G_UNLOCK (errlock);
    1329            3 : }
    1330              : 
    1331              : /**
    1332              :  * @brief Internal interface to write messages for ml_error(), relaying previously reported errors.
    1333              :  */
    1334              : void
    1335            0 : _ml_error_report_continue_ (const char *fmt, ...)
    1336              : {
    1337            0 :   size_t cursor = 0;
    1338              :   va_list arg_ptr;
    1339              :   char buf[_ML_ERRORMSG_LENGTH];
    1340            0 :   G_LOCK (errlock);
    1341              : 
    1342              :   /* Check if there is a message to relay */
    1343            0 :   if (reported == 0) {
    1344            0 :     cursor = strlen (errormsg);
    1345            0 :     if (cursor < (_ML_ERRORMSG_LENGTH - 1)) {
    1346            0 :       errormsg[cursor] = '\n';
    1347            0 :       errormsg[cursor + 1] = '\0';
    1348            0 :       cursor++;
    1349              :     }
    1350              :   } else {
    1351            0 :     errormsg[0] = '\0';
    1352              :   }
    1353              : 
    1354            0 :   va_start (arg_ptr, fmt);
    1355            0 :   vsnprintf (buf, _ML_ERRORMSG_LENGTH - 1, fmt, arg_ptr);
    1356            0 :   _ml_loge ("%s", buf);
    1357              : 
    1358            0 :   memcpy (errormsg + cursor, buf, _ML_ERRORMSG_LENGTH - strlen (errormsg) - 1);
    1359            0 :   if (strlen (errormsg) >= (_ML_ERRORMSG_LENGTH - 2)) {
    1360            0 :     errormsg[_ML_ERRORMSG_LENGTH - 2] = '.';
    1361            0 :     errormsg[_ML_ERRORMSG_LENGTH - 3] = '.';
    1362            0 :     errormsg[_ML_ERRORMSG_LENGTH - 4] = '.';
    1363              :   }
    1364              : 
    1365            0 :   va_end (arg_ptr);
    1366              : 
    1367            0 :   errormsg[_ML_ERRORMSG_LENGTH - 1] = '\0';
    1368            0 :   reported = 0;
    1369            0 :   G_UNLOCK (errlock);
    1370            0 : }
    1371              : 
    1372              : static const char *strerrors[] = {
    1373              :   [0] = "Not an error",
    1374              :   [EINVAL] =
    1375              :       "Invalid parameters are given to a function. Check parameter values. (EINVAL)",
    1376              : };
    1377              : 
    1378              : /**
    1379              :  * @brief public API function of error code descriptions
    1380              :  */
    1381              : const char *
    1382            0 : ml_strerror (int errnum)
    1383              : {
    1384            0 :   int size = sizeof (strerrors) / sizeof (strerrors[0]);
    1385              : 
    1386            0 :   if (errnum < 0)
    1387            0 :     errnum = errnum * -1;
    1388              : 
    1389            0 :   if (errnum == 0 || errnum >= size)
    1390            0 :     return NULL;
    1391            0 :   return strerrors[errnum];
    1392              : }
    1393              : 
    1394              : /**
    1395              :  * @brief Internal function to check the handle is valid.
    1396              :  */
    1397              : static bool
    1398            0 : _ml_info_is_valid (gpointer handle, ml_info_type_e expected)
    1399              : {
    1400              :   ml_info_type_e current;
    1401              : 
    1402            0 :   if (!handle)
    1403            0 :     return false;
    1404              : 
    1405              :   /* The first field should be an enum value of ml_info_type_e. */
    1406            0 :   current = *((ml_info_type_e *) handle);
    1407            0 :   if (current != expected)
    1408            0 :     return false;
    1409              : 
    1410            0 :   switch (current) {
    1411            0 :     case ML_INFO_TYPE_OPTION:
    1412              :     case ML_INFO_TYPE_INFORMATION:
    1413              :     {
    1414            0 :       ml_info_s *_info = (ml_info_s *) handle;
    1415              : 
    1416            0 :       if (!_info->table)
    1417            0 :         return false;
    1418              : 
    1419            0 :       break;
    1420              :     }
    1421            0 :     case ML_INFO_TYPE_INFORMATION_LIST:
    1422            0 :       break;
    1423            0 :     default:
    1424              :       /* Unknown type */
    1425            0 :       return false;
    1426              :   }
    1427              : 
    1428            0 :   return true;
    1429              : }
    1430              : 
    1431              : /**
    1432              :  * @brief Internal function for destroy value of option table
    1433              :  */
    1434              : static void
    1435            0 : _ml_info_value_free (gpointer data)
    1436              : {
    1437              :   ml_info_value_s *_value;
    1438              : 
    1439            0 :   _value = (ml_info_value_s *) data;
    1440            0 :   if (_value) {
    1441            0 :     if (_value->destroy)
    1442            0 :       _value->destroy (_value->value);
    1443            0 :     g_free (_value);
    1444              :   }
    1445            0 : }
    1446              : 
    1447              : /**
    1448              :  * @brief Internal function for create ml_info
    1449              :  */
    1450              : static ml_info_s *
    1451            0 : _ml_info_create (ml_info_type_e type)
    1452              : {
    1453              :   ml_info_s *info;
    1454              : 
    1455            0 :   info = g_new0 (ml_info_s, 1);
    1456            0 :   if (info == NULL) {
    1457            0 :     _ml_error_report
    1458              :         ("Failed to allocate memory for the ml_info. Out of memory?");
    1459            0 :     return NULL;
    1460              :   }
    1461              : 
    1462            0 :   info->type = type;
    1463            0 :   info->table =
    1464            0 :       g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
    1465              :       _ml_info_value_free);
    1466            0 :   if (info->table == NULL) {
    1467            0 :     _ml_error_report
    1468              :         ("Failed to allocate memory for the table of ml_info. Out of memory?");
    1469            0 :     g_free (info);
    1470            0 :     return NULL;
    1471              :   }
    1472              : 
    1473            0 :   return info;
    1474              : }
    1475              : 
    1476              : /**
    1477              :  * @brief Internal function for destroy ml_info
    1478              :  */
    1479              : static void
    1480            0 : _ml_info_destroy (gpointer data)
    1481              : {
    1482            0 :   ml_info_s *info = (ml_info_s *) data;
    1483              : 
    1484            0 :   if (!info)
    1485            0 :     return;
    1486              : 
    1487            0 :   info->type = ML_INFO_TYPE_UNKNOWN;
    1488              : 
    1489            0 :   if (info->table) {
    1490            0 :     g_hash_table_destroy (info->table);
    1491            0 :     info->table = NULL;
    1492              :   }
    1493              : 
    1494            0 :   g_free (info);
    1495            0 :   return;
    1496              : }
    1497              : 
    1498              : /**
    1499              :  * @brief Internal function for set value of given ml_info
    1500              :  */
    1501              : static int
    1502            0 : _ml_info_set_value (ml_info_s * info, const char *key, void *value,
    1503              :     ml_data_destroy_cb destroy)
    1504              : {
    1505              :   ml_info_value_s *info_value;
    1506              : 
    1507            0 :   if (!STR_IS_VALID (key))
    1508            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1509              :         "The parameter, 'key' is invalid. It should be a valid string.");
    1510              : 
    1511            0 :   if (!info || !value)
    1512            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1513              :         "The parameter, 'info' or 'value' is NULL. It should be a valid ml_info and value.");
    1514              : 
    1515            0 :   info_value = g_new0 (ml_info_value_s, 1);
    1516            0 :   if (!info_value)
    1517            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1518              :         "Failed to allocate memory for the info value. Out of memory?");
    1519              : 
    1520            0 :   info_value->value = value;
    1521            0 :   info_value->destroy = destroy;
    1522            0 :   g_hash_table_insert (info->table, g_strdup (key), (gpointer) info_value);
    1523              : 
    1524            0 :   return ML_ERROR_NONE;
    1525              : }
    1526              : 
    1527              : /**
    1528              :  * @brief Internal function for get value of given ml_info
    1529              :  */
    1530              : static int
    1531            0 : _ml_info_get_value (ml_info_s * info, const char *key, void **value)
    1532              : {
    1533              :   ml_info_value_s *info_value;
    1534              : 
    1535            0 :   if (!info || !key || !value)
    1536            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1537              :         "The parameter, 'info', 'key' or 'value' is NULL. It should be a valid ml_info, key and value.");
    1538              : 
    1539            0 :   info_value = g_hash_table_lookup (info->table, key);
    1540            0 :   if (!info_value) {
    1541            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1542              :         "Failed to find a value of key '%s', invalid key string?", key);
    1543              :   }
    1544              : 
    1545            0 :   *value = info_value->value;
    1546              : 
    1547            0 :   return ML_ERROR_NONE;
    1548              : }
    1549              : 
    1550              : /**
    1551              :  * @brief Creates an option and returns the instance a handle.
    1552              :  */
    1553              : int
    1554            0 : ml_option_create (ml_option_h * option)
    1555              : {
    1556            0 :   ml_info_s *_option = NULL;
    1557              : 
    1558            0 :   check_feature_state (ML_FEATURE);
    1559              : 
    1560            0 :   if (!option) {
    1561            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1562              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h");
    1563              :   }
    1564              : 
    1565            0 :   _option = _ml_info_create (ML_INFO_TYPE_OPTION);
    1566            0 :   if (_option == NULL)
    1567            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1568              :         "Failed to allocate memory for the option handle. Out of memory?");
    1569              : 
    1570            0 :   *option = _option;
    1571            0 :   return ML_ERROR_NONE;
    1572              : }
    1573              : 
    1574              : /**
    1575              :  * @brief Frees the given handle of a ml_option.
    1576              :  */
    1577              : int
    1578            0 : ml_option_destroy (ml_option_h option)
    1579              : {
    1580            0 :   check_feature_state (ML_FEATURE);
    1581              : 
    1582            0 :   if (!option) {
    1583            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1584              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1585              :   }
    1586              : 
    1587            0 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1588            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1589              :         "The parameter, 'option' is not a ml-option handle.");
    1590              : 
    1591            0 :   _ml_info_destroy (option);
    1592              : 
    1593            0 :   return ML_ERROR_NONE;
    1594              : }
    1595              : 
    1596              : /**
    1597              :  * @brief Set key-value pair in given option handle. Note that if duplicated key is given, the value is updated with the new one.
    1598              :  * If some options are changed or there are newly added options, please modify below description.
    1599              :  * The list of valid key-values are:
    1600              :  *
    1601              :  * key (char *)     || value (expected type (pointer))
    1602              :  * ---------------------------------------------------------
    1603              :  * "framework_name" ||  explicit name of framework (char *)
    1604              :  * ...
    1605              :  */
    1606              : int
    1607            0 : ml_option_set (ml_option_h option, const char *key, void *value,
    1608              :     ml_data_destroy_cb destroy)
    1609              : {
    1610            0 :   check_feature_state (ML_FEATURE);
    1611              : 
    1612            0 :   if (!option) {
    1613            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1614              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1615              :   }
    1616              : 
    1617            0 :   if (!key) {
    1618            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1619              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1620              :   }
    1621              : 
    1622            0 :   if (!value) {
    1623            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1624              :         "The parameter, 'value' is NULL. It should be a valid void*");
    1625              :   }
    1626              : 
    1627            0 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1628            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1629              :         "The parameter, 'option' is not a ml-option handle.");
    1630              : 
    1631            0 :   return _ml_info_set_value ((ml_info_s *) option, key, value, destroy);
    1632              : }
    1633              : 
    1634              : /**
    1635              :  * @brief Gets a value of key in ml_option instance.
    1636              :  */
    1637              : int
    1638            0 : ml_option_get (ml_option_h option, const char *key, void **value)
    1639              : {
    1640            0 :   check_feature_state (ML_FEATURE);
    1641              : 
    1642            0 :   if (!option) {
    1643            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1644              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1645              :   }
    1646              : 
    1647            0 :   if (!key) {
    1648            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1649              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1650              :   }
    1651              : 
    1652            0 :   if (!value) {
    1653            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1654              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1655              :   }
    1656              : 
    1657            0 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1658            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1659              :         "The parameter, 'option' is not a ml-option handle.");
    1660              : 
    1661            0 :   return _ml_info_get_value ((ml_info_s *) option, key, value);
    1662              : }
    1663              : 
    1664              : /**
    1665              :  * @brief Creates an ml_information instance and returns the handle.
    1666              :  */
    1667              : int
    1668            0 : _ml_information_create (ml_information_h * info)
    1669              : {
    1670            0 :   ml_info_s *_info = NULL;
    1671              : 
    1672            0 :   check_feature_state (ML_FEATURE);
    1673              : 
    1674            0 :   if (!info) {
    1675            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1676              :         "The parameter, 'info' is NULL. It should be a valid ml_information_h");
    1677              :   }
    1678              : 
    1679            0 :   _info = _ml_info_create (ML_INFO_TYPE_INFORMATION);
    1680            0 :   if (!_info)
    1681            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1682              :         "Failed to allocate memory for the info handle. Out of memory?");
    1683              : 
    1684            0 :   *info = _info;
    1685            0 :   return ML_ERROR_NONE;
    1686              : }
    1687              : 
    1688              : /**
    1689              :  * @brief Set key-value pair in given information handle.
    1690              :  * @note If duplicated key is given, the value is updated with the new one.
    1691              :  */
    1692              : int
    1693            0 : _ml_information_set (ml_information_h information, const char *key, void *value,
    1694              :     ml_data_destroy_cb destroy)
    1695              : {
    1696            0 :   check_feature_state (ML_FEATURE);
    1697              : 
    1698            0 :   if (!information) {
    1699            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1700              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1701              :   }
    1702              : 
    1703            0 :   if (!key) {
    1704            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1705              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1706              :   }
    1707              : 
    1708            0 :   if (!value) {
    1709            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1710              :         "The parameter, 'value' is NULL. It should be a valid void*");
    1711              :   }
    1712              : 
    1713            0 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1714            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1715              :         "The parameter, 'information' is not a ml-information handle.");
    1716              : 
    1717            0 :   return _ml_info_set_value ((ml_info_s *) information, key, value, destroy);
    1718              : }
    1719              : 
    1720              : /**
    1721              :  * @brief Internal function to iterate ml-information.
    1722              :  */
    1723              : static void
    1724            0 : _ml_information_iter_internal (gpointer key, gpointer value, gpointer user_data)
    1725              : {
    1726            0 :   ml_info_iter_data_s *iter = (ml_info_iter_data_s *) user_data;
    1727            0 :   ml_info_value_s *info_value = (ml_info_value_s *) value;
    1728              : 
    1729            0 :   iter->callback (key, info_value->value, iter->user_data);
    1730            0 : }
    1731              : 
    1732              : /**
    1733              :  * @brief Iterates the key and value of each pair in ml-information.
    1734              :  */
    1735              : int
    1736            0 : ml_information_iterate (ml_information_h ml_info,
    1737              :     ml_information_iterate_cb cb, void *user_data)
    1738              : {
    1739              :   ml_info_s *_info;
    1740              :   ml_info_iter_data_s *iter;
    1741              : 
    1742            0 :   check_feature_state (ML_FEATURE);
    1743              : 
    1744            0 :   if (!_ml_info_is_valid (ml_info, ML_INFO_TYPE_INFORMATION)) {
    1745            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1746              :         "The parameter, 'ml_info' is not a ml-information handle.");
    1747              :   }
    1748              : 
    1749            0 :   if (!cb) {
    1750            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1751              :         "The parameter, 'cb' is NULL. It should be a valid function.");
    1752              :   }
    1753              : 
    1754            0 :   _info = (ml_info_s *) ml_info;
    1755              : 
    1756            0 :   iter = g_new0 (ml_info_iter_data_s, 1);
    1757            0 :   if (!iter) {
    1758            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1759              :         "Failed to allocate memory for the iteration. Out of memory?");
    1760              :   }
    1761              : 
    1762            0 :   iter->callback = cb;
    1763            0 :   iter->user_data = user_data;
    1764              : 
    1765            0 :   g_hash_table_foreach (_info->table, _ml_information_iter_internal, iter);
    1766            0 :   g_free (iter);
    1767              : 
    1768            0 :   return ML_ERROR_NONE;
    1769              : }
    1770              : 
    1771              : /**
    1772              :  * @brief Frees the given handle of a ml_information.
    1773              :  */
    1774              : int
    1775            0 : ml_information_destroy (ml_information_h information)
    1776              : {
    1777            0 :   check_feature_state (ML_FEATURE);
    1778              : 
    1779            0 :   if (!information) {
    1780            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1781              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1782              :   }
    1783              : 
    1784            0 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1785            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1786              :         "The parameter, 'information' is not a ml-information handle.");
    1787              : 
    1788            0 :   _ml_info_destroy (information);
    1789              : 
    1790            0 :   return ML_ERROR_NONE;
    1791              : }
    1792              : 
    1793              : /**
    1794              :  * @brief Gets the value corresponding to the given key in ml_information instance.
    1795              :  */
    1796              : int
    1797            0 : ml_information_get (ml_information_h information, const char *key, void **value)
    1798              : {
    1799            0 :   check_feature_state (ML_FEATURE);
    1800              : 
    1801            0 :   if (!information) {
    1802            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1803              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1804              :   }
    1805              : 
    1806            0 :   if (!key) {
    1807            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1808              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1809              :   }
    1810              : 
    1811            0 :   if (!value) {
    1812            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1813              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1814              :   }
    1815              : 
    1816            0 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1817            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1818              :         "The parameter, 'information' is not a ml-information handle.");
    1819              : 
    1820            0 :   return _ml_info_get_value ((ml_info_s *) information, key, value);
    1821              : }
    1822              : 
    1823              : /**
    1824              :  * @brief Creates an ml-information-list instance and returns the handle.
    1825              :  */
    1826              : int
    1827            0 : _ml_information_list_create (ml_information_list_h * list)
    1828              : {
    1829              :   ml_info_list_s *_info_list;
    1830              : 
    1831            0 :   check_feature_state (ML_FEATURE);
    1832              : 
    1833            0 :   if (!list)
    1834            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1835              :         "The parameter, 'list' is NULL. It should be a valid ml_information_list_h.");
    1836              : 
    1837            0 :   _info_list = g_try_new0 (ml_info_list_s, 1);
    1838            0 :   if (!_info_list) {
    1839            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1840              :         "Failed to allocate memory for ml_information_list_h. Out of memory?");
    1841              :   }
    1842              : 
    1843            0 :   _info_list->type = ML_INFO_TYPE_INFORMATION_LIST;
    1844              : 
    1845            0 :   *list = _info_list;
    1846            0 :   return ML_ERROR_NONE;
    1847              : }
    1848              : 
    1849              : /**
    1850              :  * @brief Adds an ml-information into ml-information-list.
    1851              :  */
    1852              : int
    1853            0 : _ml_information_list_add (ml_information_list_h list, ml_information_h info)
    1854              : {
    1855              :   ml_info_list_s *_info_list;
    1856              : 
    1857            0 :   check_feature_state (ML_FEATURE);
    1858              : 
    1859            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1860            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1861              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1862              :   }
    1863              : 
    1864            0 :   if (!_ml_info_is_valid (info, ML_INFO_TYPE_OPTION) &&
    1865            0 :       !_ml_info_is_valid (info, ML_INFO_TYPE_INFORMATION)) {
    1866            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1867              :         "The parameter, 'info' is invalid. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1868              :   }
    1869              : 
    1870            0 :   _info_list = (ml_info_list_s *) list;
    1871            0 :   _info_list->info = g_slist_append (_info_list->info, info);
    1872              : 
    1873            0 :   return ML_ERROR_NONE;
    1874              : }
    1875              : 
    1876              : /**
    1877              :  * @brief Destroys the ml-information-list instance.
    1878              :  */
    1879              : int
    1880            0 : ml_information_list_destroy (ml_information_list_h list)
    1881              : {
    1882              :   ml_info_list_s *_info_list;
    1883              : 
    1884            0 :   check_feature_state (ML_FEATURE);
    1885              : 
    1886            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1887            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1888              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1889              :   }
    1890              : 
    1891            0 :   _info_list = (ml_info_list_s *) list;
    1892            0 :   g_slist_free_full (_info_list->info, _ml_info_destroy);
    1893            0 :   g_free (_info_list);
    1894              : 
    1895            0 :   return ML_ERROR_NONE;
    1896              : }
    1897              : 
    1898              : /**
    1899              :  * @brief Gets the number of ml-information in ml-information-list instance.
    1900              :  */
    1901              : int
    1902            0 : ml_information_list_length (ml_information_list_h list, unsigned int *length)
    1903              : {
    1904              :   ml_info_list_s *_info_list;
    1905              : 
    1906            0 :   check_feature_state (ML_FEATURE);
    1907              : 
    1908            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1909            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1910              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1911              :   }
    1912              : 
    1913            0 :   if (!length) {
    1914            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1915              :         "The parameter, 'length' is NULL. It should be a valid unsigned int*");
    1916              :   }
    1917              : 
    1918            0 :   _info_list = (ml_info_list_s *) list;
    1919            0 :   *length = g_slist_length (_info_list->info);
    1920              : 
    1921            0 :   return ML_ERROR_NONE;
    1922              : }
    1923              : 
    1924              : /**
    1925              :  * @brief Gets a ml-information in ml-information-list instance with given index.
    1926              :  */
    1927              : int
    1928            0 : ml_information_list_get (ml_information_list_h list, unsigned int index,
    1929              :     ml_information_h * information)
    1930              : {
    1931              :   ml_info_list_s *_info_list;
    1932              : 
    1933            0 :   check_feature_state (ML_FEATURE);
    1934              : 
    1935            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1936            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1937              :         "The parameter, 'list' is NULL. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1938              :   }
    1939              : 
    1940            0 :   if (!information) {
    1941            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1942              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h*");
    1943              :   }
    1944              : 
    1945            0 :   _info_list = (ml_info_list_s *) list;
    1946            0 :   *information = g_slist_nth_data (_info_list->info, index);
    1947              : 
    1948            0 :   if (*information == NULL) {
    1949            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1950              :         "The parameter, 'index' is invalid. It should be less than the length of ml_information_list_h.");
    1951              :   }
    1952              : 
    1953            0 :   return ML_ERROR_NONE;
    1954              : }
        

Generated by: LCOV version 2.4-0