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#71aaab1ba3fd2982615440cd18a42aca943ff2ec Lines: 0.0 % 776 0
Test Date: 2025-10-25 01:57:17 Functions: 0.0 % 60 0

            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            0 : _ml_tensors_info_create_internal (ml_tensors_info_h * info, bool extended)
     135              : {
     136              :   ml_tensors_info_s *tensors_info;
     137              : 
     138            0 :   check_feature_state (ML_FEATURE);
     139              : 
     140            0 :   if (!info)
     141            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     142              :         "The parameter, info, is NULL. Provide a valid pointer.");
     143              : 
     144            0 :   *info = tensors_info = g_new0 (ml_tensors_info_s, 1);
     145            0 :   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            0 :   g_mutex_init (&tensors_info->lock);
     150            0 :   tensors_info->is_extended = extended;
     151              : 
     152              :   /* init tensors info struct */
     153            0 :   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            0 : ml_tensors_info_create (ml_tensors_info_h * info)
     187              : {
     188            0 :   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            0 : ml_tensors_info_destroy (ml_tensors_info_h info)
     205              : {
     206              :   ml_tensors_info_s *tensors_info;
     207              : 
     208            0 :   check_feature_state (ML_FEATURE);
     209              : 
     210            0 :   tensors_info = (ml_tensors_info_s *) info;
     211              : 
     212            0 :   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            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     217            0 :   _ml_tensors_info_free (tensors_info);
     218            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     219              : 
     220            0 :   g_mutex_clear (&tensors_info->lock);
     221            0 :   g_free (tensors_info);
     222              : 
     223            0 :   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            0 : ml_tensors_info_set_count (ml_tensors_info_h info, unsigned int count)
     291              : {
     292              :   ml_tensors_info_s *tensors_info;
     293              : 
     294            0 :   check_feature_state (ML_FEATURE);
     295              : 
     296            0 :   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            0 :   if (count > ML_TENSOR_SIZE_LIMIT || count == 0)
     300            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     305              : 
     306              :   /* This is atomic. No need for locks */
     307            0 :   tensors_info->info.num_tensors = count;
     308              : 
     309            0 :   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_free (_info->name);
     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            0 : 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            0 :   check_feature_state (ML_FEATURE);
     427              : 
     428            0 :   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            0 :   if (type >= ML_TENSOR_TYPE_UNKNOWN || type < 0)
     433            0 :     _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            0 :   if (type == ML_TENSOR_TYPE_FLOAT16)
     439            0 :     _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            0 : _ml_tensors_info_initialize (ml_tensors_info_s * info)
     662              : {
     663            0 :   if (!info)
     664            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     665              :         "The parameter, info, is NULL. Provide a valid pointer.");
     666              : 
     667            0 :   gst_tensors_info_init (&info->info);
     668              : 
     669            0 :   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            0 : _ml_tensors_info_free (ml_tensors_info_s * info)
     678              : {
     679            0 :   if (!info)
     680            0 :     return;
     681              : 
     682            0 :   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 < ML_TENSOR_SIZE_LIMIT; i++) {
     716            0 :         if (_data->tensors[i].data) {
     717            0 :           g_free (_data->tensors[i].data);
     718            0 :           _data->tensors[i].data = NULL;
     719              :         }
     720              :       }
     721              :     }
     722              :   }
     723              : 
     724            0 :   if (_data->info)
     725            0 :     ml_tensors_info_destroy (_data->info);
     726              : 
     727            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     728            0 :   g_mutex_clear (&_data->lock);
     729            0 :   g_free (_data);
     730            0 :   return status;
     731              : }
     732              : 
     733              : /**
     734              :  * @brief Frees the tensors data pointer.
     735              :  * @note This does not touch the lock
     736              :  */
     737              : int
     738            0 : ml_tensors_data_destroy (ml_tensors_data_h data)
     739              : {
     740              :   int ret;
     741            0 :   check_feature_state (ML_FEATURE);
     742            0 :   ret = _ml_tensors_data_destroy_internal (data, TRUE);
     743            0 :   if (ret != ML_ERROR_NONE)
     744            0 :     _ml_error_report_return_continue (ret,
     745              :         "Call to _ml_tensors_data_destroy_internal failed with %d", ret);
     746            0 :   return ret;
     747              : }
     748              : 
     749              : /**
     750              :  * @brief Creates a tensor data frame without buffer with the given tensors information.
     751              :  * @note Memory for tensor data buffers is not allocated.
     752              :  */
     753              : int
     754            0 : _ml_tensors_data_create_no_alloc (const ml_tensors_info_h info,
     755              :     ml_tensors_data_h * data)
     756              : {
     757              :   ml_tensors_data_s *_data;
     758              :   ml_tensors_info_s *_info;
     759              :   guint i;
     760            0 :   int status = ML_ERROR_NONE;
     761              : 
     762            0 :   check_feature_state (ML_FEATURE);
     763              : 
     764            0 :   if (data == NULL)
     765            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     766              :         "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);.");
     767              : 
     768              :   /* init null */
     769            0 :   *data = NULL;
     770              : 
     771            0 :   _data = g_new0 (ml_tensors_data_s, 1);
     772            0 :   if (!_data)
     773            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     774              :         "Failed to allocate memory for tensors data. Probably the system is out of memory.");
     775              : 
     776            0 :   g_mutex_init (&_data->lock);
     777              : 
     778            0 :   _info = (ml_tensors_info_s *) info;
     779            0 :   if (_info != NULL) {
     780            0 :     status = _ml_tensors_info_create_from (info, &_data->info);
     781            0 :     if (status != ML_ERROR_NONE) {
     782            0 :       _ml_error_report_continue
     783              :           ("Failed to create internal information handle for tensors data.");
     784            0 :       goto error;
     785              :     }
     786              : 
     787            0 :     G_LOCK_UNLESS_NOLOCK (*_info);
     788            0 :     _data->num_tensors = _info->info.num_tensors;
     789            0 :     for (i = 0; i < _data->num_tensors; i++) {
     790            0 :       _data->tensors[i].size = gst_tensors_info_get_size (&_info->info, i);
     791            0 :       _data->tensors[i].data = NULL;
     792              :     }
     793            0 :     G_UNLOCK_UNLESS_NOLOCK (*_info);
     794              :   }
     795              : 
     796            0 : error:
     797            0 :   if (status == ML_ERROR_NONE) {
     798            0 :     *data = _data;
     799              :   } else {
     800            0 :     _ml_tensors_data_destroy_internal (_data, FALSE);
     801              :   }
     802              : 
     803            0 :   return status;
     804              : }
     805              : 
     806              : /**
     807              :  * @brief Clones the given tensor data frame from the given tensors data. (more info in nnstreamer.h)
     808              :  * @note Memory ptr for data buffer is copied. No new memory for data buffer is allocated.
     809              :  */
     810              : int
     811            0 : _ml_tensors_data_clone_no_alloc (const ml_tensors_data_s * data_src,
     812              :     ml_tensors_data_h * data)
     813              : {
     814              :   int status;
     815              :   ml_tensors_data_s *_data;
     816              : 
     817            0 :   check_feature_state (ML_FEATURE);
     818              : 
     819            0 :   if (data == NULL)
     820            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     821              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     822            0 :   if (data_src == NULL)
     823            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     824              :         "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).");
     825              : 
     826            0 :   status = _ml_tensors_data_create_no_alloc (data_src->info,
     827              :       (ml_tensors_data_h *) & _data);
     828            0 :   if (status != ML_ERROR_NONE)
     829            0 :     _ml_error_report_return_continue (status,
     830              :         "The call to _ml_tensors_data_create_no_alloc has failed with %d.",
     831              :         status);
     832              : 
     833            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
     834              : 
     835            0 :   _data->num_tensors = data_src->num_tensors;
     836            0 :   memcpy (_data->tensors, data_src->tensors,
     837            0 :       sizeof (GstTensorMemory) * data_src->num_tensors);
     838              : 
     839            0 :   *data = _data;
     840            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     841            0 :   return ML_ERROR_NONE;
     842              : }
     843              : 
     844              : /**
     845              :  * @brief  Allocates zero-initialized memory of the given size for the tensor at the specified index
     846              :  * in the tensor data structure, and sets the size value for that tensor.
     847              :  */
     848              : static int
     849            0 : _ml_tensor_data_alloc (ml_tensors_data_s * data, guint index, const size_t size)
     850              : {
     851            0 :   if (!data || index >= data->num_tensors || size <= 0)
     852            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     853              :         "Invalid parameter: data is invalid, or index is out of range.");
     854              : 
     855            0 :   data->tensors[index].size = size;
     856            0 :   data->tensors[index].data = g_malloc0 (size);
     857            0 :   if (data->tensors[index].data == NULL)
     858            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     859              :         "Failed to allocate memory for tensor data.");
     860              : 
     861            0 :   return ML_ERROR_NONE;
     862              : }
     863              : 
     864              : /**
     865              :  * @brief Copies the tensor data frame.
     866              :  */
     867              : int
     868            0 : ml_tensors_data_clone (const ml_tensors_data_h in, ml_tensors_data_h * out)
     869              : {
     870              :   int status;
     871              :   unsigned int i;
     872            0 :   ml_tensors_data_s *_in, *_out = NULL;
     873              : 
     874            0 :   check_feature_state (ML_FEATURE);
     875              : 
     876            0 :   if (in == NULL)
     877            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     878              :         "The parameter, in, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     879              : 
     880            0 :   if (out == NULL)
     881            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     882              :         "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);.");
     883              : 
     884            0 :   _in = (ml_tensors_data_s *) in;
     885            0 :   G_LOCK_UNLESS_NOLOCK (*_in);
     886              : 
     887            0 :   status = ml_tensors_data_create (_in->info, out);
     888            0 :   if (status != ML_ERROR_NONE) {
     889            0 :     _ml_loge ("Failed to create new handle to copy tensor data.");
     890            0 :     goto error;
     891              :   }
     892              : 
     893            0 :   _out = (ml_tensors_data_s *) (*out);
     894              : 
     895            0 :   for (i = 0; i < _out->num_tensors; ++i) {
     896            0 :     if (!_out->tensors[i].data) {
     897              :       /**
     898              :        * If tensor format is static, memory is already allocated.
     899              :        * However, flexible tensor is not. To copy raw data, allocate new memory here.
     900              :        */
     901            0 :       status = _ml_tensor_data_alloc (_out, i, _in->tensors[i].size);
     902            0 :       if (status != ML_ERROR_NONE) {
     903            0 :         goto error;
     904              :       }
     905              :     }
     906              : 
     907            0 :     memcpy (_out->tensors[i].data, _in->tensors[i].data, _in->tensors[i].size);
     908              :   }
     909              : 
     910            0 : error:
     911            0 :   if (status != ML_ERROR_NONE) {
     912              :     /* Failed to create new data handle. */
     913            0 :     _ml_tensors_data_destroy_internal (_out, TRUE);
     914            0 :     *out = NULL;
     915              :   }
     916              : 
     917            0 :   G_UNLOCK_UNLESS_NOLOCK (*_in);
     918            0 :   return status;
     919              : }
     920              : 
     921              : /**
     922              :  * @brief Gets the tensors information of given tensor data frame.
     923              :  */
     924              : int
     925            0 : ml_tensors_data_get_info (const ml_tensors_data_h data,
     926              :     ml_tensors_info_h * info)
     927              : {
     928              :   int status;
     929              :   ml_tensors_data_s *_data;
     930              : 
     931            0 :   check_feature_state (ML_FEATURE);
     932              : 
     933            0 :   if (data == NULL) {
     934            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     935              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     936              :   }
     937              : 
     938            0 :   if (info == NULL) {
     939            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     940              :         "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);.");
     941              :   }
     942              : 
     943            0 :   _data = (ml_tensors_data_s *) data;
     944            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
     945              : 
     946            0 :   status = _ml_tensors_info_create_from (_data->info, info);
     947            0 :   if (status != ML_ERROR_NONE) {
     948            0 :     _ml_error_report_continue
     949              :         ("Failed to get the tensor information from data handle.");
     950              :   }
     951              : 
     952            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     953            0 :   return status;
     954              : }
     955              : 
     956              : /**
     957              :  * @brief Allocates a tensor data frame with the given tensors info. (more info in nnstreamer.h)
     958              :  */
     959              : int
     960            0 : ml_tensors_data_create (const ml_tensors_info_h info, ml_tensors_data_h * data)
     961              : {
     962            0 :   int status = ML_ERROR_NONE;
     963            0 :   ml_tensors_info_s *_info = NULL;
     964            0 :   ml_tensors_data_s *_data = NULL;
     965              :   guint i;
     966              :   bool valid;
     967              : 
     968            0 :   check_feature_state (ML_FEATURE);
     969              : 
     970            0 :   if (info == NULL)
     971            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     972              :         "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().");
     973            0 :   if (data == NULL)
     974            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     975              :         "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);.");
     976              : 
     977            0 :   status = ml_tensors_info_validate (info, &valid);
     978            0 :   if (status != ML_ERROR_NONE)
     979            0 :     _ml_error_report_return_continue (status,
     980              :         "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.");
     981            0 :   if (!valid)
     982            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     983              :         "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.");
     984              : 
     985              :   status =
     986            0 :       _ml_tensors_data_create_no_alloc (info, (ml_tensors_data_h *) & _data);
     987              : 
     988            0 :   if (status != ML_ERROR_NONE) {
     989            0 :     _ml_error_report_return_continue (status,
     990              :         "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.",
     991              :         status);
     992              :   }
     993              : 
     994            0 :   _info = (ml_tensors_info_s *) info;
     995            0 :   if (_info->info.format == _NNS_TENSOR_FORMAT_STATIC) {
     996            0 :     for (i = 0; i < _data->num_tensors; i++) {
     997            0 :       status = _ml_tensor_data_alloc (_data, i, _data->tensors[i].size);
     998            0 :       if (status != ML_ERROR_NONE)
     999            0 :         goto error;
    1000              :     }
    1001              :   } else {
    1002            0 :     _ml_logw
    1003              :         ("[ml_tensors_data_create] format is not static, skipping tensor memory allocation. Use ml_tensors_data_set_tensor_data() to update data buffer.");
    1004              :   }
    1005              : 
    1006            0 : error:
    1007            0 :   if (status == ML_ERROR_NONE) {
    1008            0 :     *data = _data;
    1009              :   } else {
    1010            0 :     _ml_tensors_data_destroy_internal (_data, TRUE);
    1011              :   }
    1012              : 
    1013            0 :   return status;
    1014              : }
    1015              : 
    1016              : /**
    1017              :  * @brief Gets a tensor data of given handle.
    1018              :  */
    1019              : int
    1020            0 : ml_tensors_data_get_tensor_data (ml_tensors_data_h data, unsigned int index,
    1021              :     void **raw_data, size_t *data_size)
    1022              : {
    1023              :   ml_tensors_data_s *_data;
    1024            0 :   int status = ML_ERROR_NONE;
    1025              : 
    1026            0 :   check_feature_state (ML_FEATURE);
    1027              : 
    1028            0 :   if (data == NULL)
    1029            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1030              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
    1031            0 :   if (raw_data == NULL)
    1032            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1033              :         "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.");
    1034            0 :   if (data_size == NULL)
    1035            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1036              :         "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.");
    1037              : 
    1038            0 :   _data = (ml_tensors_data_s *) data;
    1039            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
    1040              : 
    1041            0 :   if (_data->num_tensors <= index) {
    1042            0 :     _ml_error_report
    1043              :         ("The parameter, index, is out of bound. The number of tensors of 'data' is %u while you requested %u'th tensor (index = %u).",
    1044              :         _data->num_tensors, index, index);
    1045            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1046            0 :     goto report;
    1047              :   }
    1048              : 
    1049            0 :   *raw_data = _data->tensors[index].data;
    1050            0 :   *data_size = _data->tensors[index].size;
    1051              : 
    1052            0 : report:
    1053            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1054            0 :   return status;
    1055              : }
    1056              : 
    1057              : /**
    1058              :  * @brief Copies a tensor data to given handle.
    1059              :  */
    1060              : int
    1061            0 : ml_tensors_data_set_tensor_data (ml_tensors_data_h data, unsigned int index,
    1062              :     const void *raw_data, const size_t data_size)
    1063              : {
    1064            0 :   ml_tensors_info_s *_info = NULL;
    1065              :   ml_tensors_data_s *_data;
    1066            0 :   int status = ML_ERROR_NONE;
    1067              : 
    1068            0 :   check_feature_state (ML_FEATURE);
    1069              : 
    1070            0 :   if (data == NULL)
    1071            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1072              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
    1073            0 :   if (raw_data == NULL)
    1074            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1075              :         "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].",
    1076              :         index);
    1077              : 
    1078            0 :   _data = (ml_tensors_data_s *) data;
    1079            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
    1080              : 
    1081            0 :   if (_data->num_tensors <= index) {
    1082            0 :     _ml_error_report
    1083              :         ("The parameter, index, is out of bound. The number of tensors of 'data' is %u, while you've requested index of %u.",
    1084              :         _data->num_tensors, index);
    1085            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1086            0 :     goto report;
    1087              :   }
    1088              : 
    1089              :   /**
    1090              :    * By default, the tensor format is _NNS_TENSOR_FORMAT_STATIC.
    1091              :    * In this case, memory allocation and the setting of _data->tensors[index].size
    1092              :    * are already handled in ml_tensors_data_create().
    1093              :    * So for the STATIC format, both the `size` and `data` pointer should already be valid here.
    1094              :    *
    1095              :    * For FLEXIBLE format, memory may not be allocated yet and will be handled here.
    1096              :    */
    1097            0 :   _info = (ml_tensors_info_s *) _data->info;
    1098            0 :   if (_info && _info->info.format != _NNS_TENSOR_FORMAT_STATIC) {
    1099            0 :     if (!_data->tensors[index].data ||
    1100            0 :         _data->tensors[index].size != data_size) {
    1101            0 :       _ml_logw
    1102              :           ("Memory allocation was not performed in ml_tensor_data_create() when tensor format is flexible.");
    1103              : 
    1104            0 :       g_free (_data->tensors[index].data);
    1105              : 
    1106            0 :       status = _ml_tensor_data_alloc (_data, index, data_size);
    1107            0 :       if (status != ML_ERROR_NONE) {
    1108            0 :         goto report;
    1109              :       }
    1110              :     }
    1111              :   }
    1112              : 
    1113            0 :   if (data_size <= 0 || _data->tensors[index].size < data_size) {
    1114            0 :     _ml_error_report
    1115              :         ("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).",
    1116              :         data_size, index, _data->tensors[index].size);
    1117            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1118            0 :     goto report;
    1119              :   }
    1120              : 
    1121            0 :   if (_data->tensors[index].data != raw_data)
    1122            0 :     memcpy (_data->tensors[index].data, raw_data, data_size);
    1123              : 
    1124            0 : report:
    1125            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1126            0 :   return status;
    1127              : }
    1128              : 
    1129              : /**
    1130              :  * @brief Copies tensor meta info.
    1131              :  */
    1132              : int
    1133            0 : ml_tensors_info_clone (ml_tensors_info_h dest, const ml_tensors_info_h src)
    1134              : {
    1135              :   ml_tensors_info_s *dest_info, *src_info;
    1136            0 :   int status = ML_ERROR_NONE;
    1137              : 
    1138            0 :   check_feature_state (ML_FEATURE);
    1139              : 
    1140            0 :   dest_info = (ml_tensors_info_s *) dest;
    1141            0 :   src_info = (ml_tensors_info_s *) src;
    1142              : 
    1143            0 :   if (!dest_info)
    1144            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1145              :         "The parameter, dest, is NULL. It should be an allocated handle (ml_tensors_info_h), usually allocated by ml_tensors_info_create ().");
    1146            0 :   if (!src_info)
    1147            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1148              :         "The parameter, src, is NULL. It should be a handle (ml_tensors_info_h) with valid data.");
    1149              : 
    1150            0 :   G_LOCK_UNLESS_NOLOCK (*dest_info);
    1151            0 :   G_LOCK_UNLESS_NOLOCK (*src_info);
    1152              : 
    1153            0 :   if (gst_tensors_info_validate (&src_info->info)) {
    1154            0 :     dest_info->is_extended = src_info->is_extended;
    1155            0 :     gst_tensors_info_copy (&dest_info->info, &src_info->info);
    1156              :   } else {
    1157            0 :     _ml_error_report
    1158              :         ("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.",
    1159              :         ML_TENSOR_SIZE_LIMIT);
    1160            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1161              :   }
    1162              : 
    1163            0 :   G_UNLOCK_UNLESS_NOLOCK (*src_info);
    1164            0 :   G_UNLOCK_UNLESS_NOLOCK (*dest_info);
    1165              : 
    1166            0 :   return status;
    1167              : }
    1168              : 
    1169              : /**
    1170              :  * @brief Replaces string.
    1171              :  * This function deallocates the input source string.
    1172              :  * This is copied from nnstreamer/tensor_common.c by the nnstreamer maintainer.
    1173              :  * @param[in] source The input string. This will be freed when returning the replaced string.
    1174              :  * @param[in] what The string to search for.
    1175              :  * @param[in] to The string to be replaced.
    1176              :  * @param[in] delimiters The characters which specify the place to split the string. Set NULL to replace all matched string.
    1177              :  * @param[out] count The count of replaced. Set NULL if it is unnecessary.
    1178              :  * @return Newly allocated string. The returned string should be freed with g_free().
    1179              :  */
    1180              : gchar *
    1181            0 : _ml_replace_string (gchar * source, const gchar * what, const gchar * to,
    1182              :     const gchar * delimiters, guint * count)
    1183              : {
    1184              :   GString *builder;
    1185              :   gchar *start, *pos, *result;
    1186            0 :   guint changed = 0;
    1187              :   gsize len;
    1188              : 
    1189            0 :   g_return_val_if_fail (source, NULL);
    1190            0 :   g_return_val_if_fail (what && to, source);
    1191              : 
    1192            0 :   len = strlen (what);
    1193            0 :   start = source;
    1194              : 
    1195            0 :   builder = g_string_new (NULL);
    1196            0 :   while ((pos = g_strstr_len (start, -1, what)) != NULL) {
    1197            0 :     gboolean skip = FALSE;
    1198              : 
    1199            0 :     if (delimiters) {
    1200              :       const gchar *s;
    1201              :       gchar *prev, *next;
    1202              :       gboolean prev_split, next_split;
    1203              : 
    1204            0 :       prev = next = NULL;
    1205            0 :       prev_split = next_split = FALSE;
    1206              : 
    1207            0 :       if (pos != source)
    1208            0 :         prev = pos - 1;
    1209            0 :       if (*(pos + len) != '\0')
    1210            0 :         next = pos + len;
    1211              : 
    1212            0 :       for (s = delimiters; *s != '\0'; ++s) {
    1213            0 :         if (!prev || *s == *prev)
    1214            0 :           prev_split = TRUE;
    1215            0 :         if (!next || *s == *next)
    1216            0 :           next_split = TRUE;
    1217            0 :         if (prev_split && next_split)
    1218            0 :           break;
    1219              :       }
    1220              : 
    1221            0 :       if (!prev_split || !next_split)
    1222            0 :         skip = TRUE;
    1223              :     }
    1224              : 
    1225            0 :     builder = g_string_append_len (builder, start, pos - start);
    1226              : 
    1227              :     /* replace string if found */
    1228            0 :     if (skip)
    1229            0 :       builder = g_string_append_len (builder, pos, len);
    1230              :     else
    1231            0 :       builder = g_string_append (builder, to);
    1232              : 
    1233            0 :     start = pos + len;
    1234            0 :     if (!skip)
    1235            0 :       changed++;
    1236              :   }
    1237              : 
    1238              :   /* append remains */
    1239            0 :   builder = g_string_append (builder, start);
    1240            0 :   result = g_string_free (builder, FALSE);
    1241              : 
    1242            0 :   if (count)
    1243            0 :     *count = changed;
    1244              : 
    1245            0 :   g_free (source);
    1246            0 :   return result;
    1247              : }
    1248              : 
    1249              : /**
    1250              :  * @brief Converts predefined entity.
    1251              :  */
    1252              : gchar *
    1253            0 : _ml_convert_predefined_entity (const gchar * str)
    1254              : {
    1255            0 :   gchar *converted = g_strdup (str);
    1256              : 
    1257              : #if defined(__ANDROID__)
    1258              :   {
    1259              :     extern const char *nnstreamer_native_get_data_path (void);
    1260              : 
    1261              :     const char *data_path = nnstreamer_native_get_data_path ();
    1262              : 
    1263              :     converted = _ml_replace_string (converted, "@APP_DATA_PATH@", data_path,
    1264              :         NULL, NULL);
    1265              :   }
    1266              : #endif
    1267              : 
    1268            0 :   return converted;
    1269              : }
    1270              : 
    1271              : /**
    1272              :  * @brief error reporting infra
    1273              :  */
    1274              : #define _ML_ERRORMSG_LENGTH (4096U)
    1275              : static char errormsg[_ML_ERRORMSG_LENGTH] = { 0 };      /* one page limit */
    1276              : 
    1277              : static int reported = 0;
    1278              : G_LOCK_DEFINE_STATIC (errlock);
    1279              : 
    1280              : /**
    1281              :  * @brief public API function of error reporting.
    1282              :  */
    1283              : const char *
    1284            0 : ml_error (void)
    1285              : {
    1286            0 :   G_LOCK (errlock);
    1287            0 :   if (reported != 0) {
    1288            0 :     errormsg[0] = '\0';
    1289            0 :     reported = 0;
    1290              :   }
    1291            0 :   if (errormsg[0] == '\0') {
    1292            0 :     G_UNLOCK (errlock);
    1293            0 :     return NULL;
    1294              :   }
    1295              : 
    1296            0 :   reported = 1;
    1297              : 
    1298            0 :   G_UNLOCK (errlock);
    1299            0 :   return errormsg;
    1300              : }
    1301              : 
    1302              : /**
    1303              :  * @brief Internal interface to write messages for ml_error()
    1304              :  */
    1305              : void
    1306            0 : _ml_error_report_ (const char *fmt, ...)
    1307              : {
    1308              :   int n;
    1309              :   va_list arg_ptr;
    1310            0 :   G_LOCK (errlock);
    1311              : 
    1312            0 :   va_start (arg_ptr, fmt);
    1313            0 :   n = vsnprintf (errormsg, _ML_ERRORMSG_LENGTH, fmt, arg_ptr);
    1314            0 :   va_end (arg_ptr);
    1315              : 
    1316            0 :   if (n > _ML_ERRORMSG_LENGTH) {
    1317            0 :     errormsg[_ML_ERRORMSG_LENGTH - 2] = '.';
    1318            0 :     errormsg[_ML_ERRORMSG_LENGTH - 3] = '.';
    1319            0 :     errormsg[_ML_ERRORMSG_LENGTH - 4] = '.';
    1320              :   }
    1321              : 
    1322            0 :   _ml_loge ("%s", errormsg);
    1323              : 
    1324            0 :   reported = 0;
    1325              : 
    1326            0 :   G_UNLOCK (errlock);
    1327            0 : }
    1328              : 
    1329              : /**
    1330              :  * @brief Internal interface to write messages for ml_error(), relaying previously reported errors.
    1331              :  */
    1332              : void
    1333            0 : _ml_error_report_continue_ (const char *fmt, ...)
    1334              : {
    1335            0 :   size_t cursor = 0;
    1336              :   va_list arg_ptr;
    1337              :   char buf[_ML_ERRORMSG_LENGTH];
    1338            0 :   G_LOCK (errlock);
    1339              : 
    1340              :   /* Check if there is a message to relay */
    1341            0 :   if (reported == 0) {
    1342            0 :     cursor = strlen (errormsg);
    1343            0 :     if (cursor < (_ML_ERRORMSG_LENGTH - 1)) {
    1344            0 :       errormsg[cursor] = '\n';
    1345            0 :       errormsg[cursor + 1] = '\0';
    1346            0 :       cursor++;
    1347              :     }
    1348              :   } else {
    1349            0 :     errormsg[0] = '\0';
    1350              :   }
    1351              : 
    1352            0 :   va_start (arg_ptr, fmt);
    1353            0 :   vsnprintf (buf, _ML_ERRORMSG_LENGTH - 1, fmt, arg_ptr);
    1354            0 :   _ml_loge ("%s", buf);
    1355              : 
    1356            0 :   memcpy (errormsg + cursor, buf, _ML_ERRORMSG_LENGTH - strlen (errormsg) - 1);
    1357            0 :   if (strlen (errormsg) >= (_ML_ERRORMSG_LENGTH - 2)) {
    1358            0 :     errormsg[_ML_ERRORMSG_LENGTH - 2] = '.';
    1359            0 :     errormsg[_ML_ERRORMSG_LENGTH - 3] = '.';
    1360            0 :     errormsg[_ML_ERRORMSG_LENGTH - 4] = '.';
    1361              :   }
    1362              : 
    1363            0 :   va_end (arg_ptr);
    1364              : 
    1365            0 :   errormsg[_ML_ERRORMSG_LENGTH - 1] = '\0';
    1366            0 :   reported = 0;
    1367            0 :   G_UNLOCK (errlock);
    1368            0 : }
    1369              : 
    1370              : static const char *strerrors[] = {
    1371              :   [0] = "Not an error",
    1372              :   [EINVAL] =
    1373              :       "Invalid parameters are given to a function. Check parameter values. (EINVAL)",
    1374              : };
    1375              : 
    1376              : /**
    1377              :  * @brief public API function of error code descriptions
    1378              :  */
    1379              : const char *
    1380            0 : ml_strerror (int errnum)
    1381              : {
    1382            0 :   int size = sizeof (strerrors) / sizeof (strerrors[0]);
    1383              : 
    1384            0 :   if (errnum < 0)
    1385            0 :     errnum = errnum * -1;
    1386              : 
    1387            0 :   if (errnum == 0 || errnum >= size)
    1388            0 :     return NULL;
    1389            0 :   return strerrors[errnum];
    1390              : }
    1391              : 
    1392              : /**
    1393              :  * @brief Internal function to check the handle is valid.
    1394              :  */
    1395              : static bool
    1396            0 : _ml_info_is_valid (gpointer handle, ml_info_type_e expected)
    1397              : {
    1398              :   ml_info_type_e current;
    1399              : 
    1400            0 :   if (!handle)
    1401            0 :     return false;
    1402              : 
    1403              :   /* The first field should be an enum value of ml_info_type_e. */
    1404            0 :   current = *((ml_info_type_e *) handle);
    1405            0 :   if (current != expected)
    1406            0 :     return false;
    1407              : 
    1408            0 :   switch (current) {
    1409            0 :     case ML_INFO_TYPE_OPTION:
    1410              :     case ML_INFO_TYPE_INFORMATION:
    1411              :     {
    1412            0 :       ml_info_s *_info = (ml_info_s *) handle;
    1413              : 
    1414            0 :       if (!_info->table)
    1415            0 :         return false;
    1416              : 
    1417            0 :       break;
    1418              :     }
    1419            0 :     case ML_INFO_TYPE_INFORMATION_LIST:
    1420            0 :       break;
    1421            0 :     default:
    1422              :       /* Unknown type */
    1423            0 :       return false;
    1424              :   }
    1425              : 
    1426            0 :   return true;
    1427              : }
    1428              : 
    1429              : /**
    1430              :  * @brief Internal function for destroy value of option table
    1431              :  */
    1432              : static void
    1433            0 : _ml_info_value_free (gpointer data)
    1434              : {
    1435              :   ml_info_value_s *_value;
    1436              : 
    1437            0 :   _value = (ml_info_value_s *) data;
    1438            0 :   if (_value) {
    1439            0 :     if (_value->destroy)
    1440            0 :       _value->destroy (_value->value);
    1441            0 :     g_free (_value);
    1442              :   }
    1443            0 : }
    1444              : 
    1445              : /**
    1446              :  * @brief Internal function for create ml_info
    1447              :  */
    1448              : static ml_info_s *
    1449            0 : _ml_info_create (ml_info_type_e type)
    1450              : {
    1451              :   ml_info_s *info;
    1452              : 
    1453            0 :   info = g_new0 (ml_info_s, 1);
    1454            0 :   if (info == NULL) {
    1455            0 :     _ml_error_report
    1456              :         ("Failed to allocate memory for the ml_info. Out of memory?");
    1457            0 :     return NULL;
    1458              :   }
    1459              : 
    1460            0 :   info->type = type;
    1461            0 :   info->table =
    1462            0 :       g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
    1463              :       _ml_info_value_free);
    1464            0 :   if (info->table == NULL) {
    1465            0 :     _ml_error_report
    1466              :         ("Failed to allocate memory for the table of ml_info. Out of memory?");
    1467            0 :     g_free (info);
    1468            0 :     return NULL;
    1469              :   }
    1470              : 
    1471            0 :   return info;
    1472              : }
    1473              : 
    1474              : /**
    1475              :  * @brief Internal function for destroy ml_info
    1476              :  */
    1477              : static void
    1478            0 : _ml_info_destroy (gpointer data)
    1479              : {
    1480            0 :   ml_info_s *info = (ml_info_s *) data;
    1481              : 
    1482            0 :   if (!info)
    1483            0 :     return;
    1484              : 
    1485            0 :   info->type = ML_INFO_TYPE_UNKNOWN;
    1486              : 
    1487            0 :   if (info->table) {
    1488            0 :     g_hash_table_destroy (info->table);
    1489            0 :     info->table = NULL;
    1490              :   }
    1491              : 
    1492            0 :   g_free (info);
    1493            0 :   return;
    1494              : }
    1495              : 
    1496              : /**
    1497              :  * @brief Internal function for set value of given ml_info
    1498              :  */
    1499              : static int
    1500            0 : _ml_info_set_value (ml_info_s * info, const char *key, void *value,
    1501              :     ml_data_destroy_cb destroy)
    1502              : {
    1503              :   ml_info_value_s *info_value;
    1504              : 
    1505            0 :   if (!STR_IS_VALID (key))
    1506            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1507              :         "The parameter, 'key' is invalid. It should be a valid string.");
    1508              : 
    1509            0 :   if (!info || !value)
    1510            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1511              :         "The parameter, 'info' or 'value' is NULL. It should be a valid ml_info and value.");
    1512              : 
    1513            0 :   info_value = g_new0 (ml_info_value_s, 1);
    1514            0 :   if (!info_value)
    1515            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1516              :         "Failed to allocate memory for the info value. Out of memory?");
    1517              : 
    1518            0 :   info_value->value = value;
    1519            0 :   info_value->destroy = destroy;
    1520            0 :   g_hash_table_insert (info->table, g_strdup (key), (gpointer) info_value);
    1521              : 
    1522            0 :   return ML_ERROR_NONE;
    1523              : }
    1524              : 
    1525              : /**
    1526              :  * @brief Internal function for get value of given ml_info
    1527              :  */
    1528              : static int
    1529            0 : _ml_info_get_value (ml_info_s * info, const char *key, void **value)
    1530              : {
    1531              :   ml_info_value_s *info_value;
    1532              : 
    1533            0 :   if (!info || !key || !value)
    1534            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1535              :         "The parameter, 'info', 'key' or 'value' is NULL. It should be a valid ml_info, key and value.");
    1536              : 
    1537            0 :   info_value = g_hash_table_lookup (info->table, key);
    1538            0 :   if (!info_value) {
    1539            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1540              :         "Failed to find a value of key '%s', invalid key string?", key);
    1541              :   }
    1542              : 
    1543            0 :   *value = info_value->value;
    1544              : 
    1545            0 :   return ML_ERROR_NONE;
    1546              : }
    1547              : 
    1548              : /**
    1549              :  * @brief Creates an option and returns the instance a handle.
    1550              :  */
    1551              : int
    1552            0 : ml_option_create (ml_option_h * option)
    1553              : {
    1554            0 :   ml_info_s *_option = NULL;
    1555              : 
    1556            0 :   check_feature_state (ML_FEATURE);
    1557              : 
    1558            0 :   if (!option) {
    1559            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1560              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h");
    1561              :   }
    1562              : 
    1563            0 :   _option = _ml_info_create (ML_INFO_TYPE_OPTION);
    1564            0 :   if (_option == NULL)
    1565            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1566              :         "Failed to allocate memory for the option handle. Out of memory?");
    1567              : 
    1568            0 :   *option = _option;
    1569            0 :   return ML_ERROR_NONE;
    1570              : }
    1571              : 
    1572              : /**
    1573              :  * @brief Frees the given handle of a ml_option.
    1574              :  */
    1575              : int
    1576            0 : ml_option_destroy (ml_option_h option)
    1577              : {
    1578            0 :   check_feature_state (ML_FEATURE);
    1579              : 
    1580            0 :   if (!option) {
    1581            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1582              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1583              :   }
    1584              : 
    1585            0 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1586            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1587              :         "The parameter, 'option' is not a ml-option handle.");
    1588              : 
    1589            0 :   _ml_info_destroy (option);
    1590              : 
    1591            0 :   return ML_ERROR_NONE;
    1592              : }
    1593              : 
    1594              : /**
    1595              :  * @brief Set key-value pair in given option handle. Note that if duplicated key is given, the value is updated with the new one.
    1596              :  * If some options are changed or there are newly added options, please modify below description.
    1597              :  * The list of valid key-values are:
    1598              :  *
    1599              :  * key (char *)     || value (expected type (pointer))
    1600              :  * ---------------------------------------------------------
    1601              :  * "framework_name" ||  explicit name of framework (char *)
    1602              :  * ...
    1603              :  */
    1604              : int
    1605            0 : ml_option_set (ml_option_h option, const char *key, void *value,
    1606              :     ml_data_destroy_cb destroy)
    1607              : {
    1608            0 :   check_feature_state (ML_FEATURE);
    1609              : 
    1610            0 :   if (!option) {
    1611            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1612              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1613              :   }
    1614              : 
    1615            0 :   if (!key) {
    1616            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1617              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1618              :   }
    1619              : 
    1620            0 :   if (!value) {
    1621            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1622              :         "The parameter, 'value' is NULL. It should be a valid void*");
    1623              :   }
    1624              : 
    1625            0 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1626            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1627              :         "The parameter, 'option' is not a ml-option handle.");
    1628              : 
    1629            0 :   return _ml_info_set_value ((ml_info_s *) option, key, value, destroy);
    1630              : }
    1631              : 
    1632              : /**
    1633              :  * @brief Gets a value of key in ml_option instance.
    1634              :  */
    1635              : int
    1636            0 : ml_option_get (ml_option_h option, const char *key, void **value)
    1637              : {
    1638            0 :   check_feature_state (ML_FEATURE);
    1639              : 
    1640            0 :   if (!option) {
    1641            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1642              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1643              :   }
    1644              : 
    1645            0 :   if (!key) {
    1646            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1647              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1648              :   }
    1649              : 
    1650            0 :   if (!value) {
    1651            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1652              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1653              :   }
    1654              : 
    1655            0 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1656            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1657              :         "The parameter, 'option' is not a ml-option handle.");
    1658              : 
    1659            0 :   return _ml_info_get_value ((ml_info_s *) option, key, value);
    1660              : }
    1661              : 
    1662              : /**
    1663              :  * @brief Creates an ml_information instance and returns the handle.
    1664              :  */
    1665              : int
    1666            0 : _ml_information_create (ml_information_h * info)
    1667              : {
    1668            0 :   ml_info_s *_info = NULL;
    1669              : 
    1670            0 :   check_feature_state (ML_FEATURE);
    1671              : 
    1672            0 :   if (!info) {
    1673            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1674              :         "The parameter, 'info' is NULL. It should be a valid ml_information_h");
    1675              :   }
    1676              : 
    1677            0 :   _info = _ml_info_create (ML_INFO_TYPE_INFORMATION);
    1678            0 :   if (!_info)
    1679            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1680              :         "Failed to allocate memory for the info handle. Out of memory?");
    1681              : 
    1682            0 :   *info = _info;
    1683            0 :   return ML_ERROR_NONE;
    1684              : }
    1685              : 
    1686              : /**
    1687              :  * @brief Set key-value pair in given information handle.
    1688              :  * @note If duplicated key is given, the value is updated with the new one.
    1689              :  */
    1690              : int
    1691            0 : _ml_information_set (ml_information_h information, const char *key, void *value,
    1692              :     ml_data_destroy_cb destroy)
    1693              : {
    1694            0 :   check_feature_state (ML_FEATURE);
    1695              : 
    1696            0 :   if (!information) {
    1697            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1698              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1699              :   }
    1700              : 
    1701            0 :   if (!key) {
    1702            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1703              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1704              :   }
    1705              : 
    1706            0 :   if (!value) {
    1707            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1708              :         "The parameter, 'value' is NULL. It should be a valid void*");
    1709              :   }
    1710              : 
    1711            0 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1712            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1713              :         "The parameter, 'information' is not a ml-information handle.");
    1714              : 
    1715            0 :   return _ml_info_set_value ((ml_info_s *) information, key, value, destroy);
    1716              : }
    1717              : 
    1718              : /**
    1719              :  * @brief Internal function to iterate ml-information.
    1720              :  */
    1721              : static void
    1722            0 : _ml_information_iter_internal (gpointer key, gpointer value, gpointer user_data)
    1723              : {
    1724            0 :   ml_info_iter_data_s *iter = (ml_info_iter_data_s *) user_data;
    1725            0 :   ml_info_value_s *info_value = (ml_info_value_s *) value;
    1726              : 
    1727            0 :   iter->callback (key, info_value->value, iter->user_data);
    1728            0 : }
    1729              : 
    1730              : /**
    1731              :  * @brief Iterates the key and value of each pair in ml-information.
    1732              :  */
    1733              : int
    1734            0 : ml_information_iterate (ml_information_h ml_info,
    1735              :     ml_information_iterate_cb cb, void *user_data)
    1736              : {
    1737              :   ml_info_s *_info;
    1738              :   ml_info_iter_data_s *iter;
    1739              : 
    1740            0 :   check_feature_state (ML_FEATURE);
    1741              : 
    1742            0 :   if (!_ml_info_is_valid (ml_info, ML_INFO_TYPE_INFORMATION)) {
    1743            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1744              :         "The parameter, 'ml_info' is not a ml-information handle.");
    1745              :   }
    1746              : 
    1747            0 :   if (!cb) {
    1748            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1749              :         "The parameter, 'cb' is NULL. It should be a valid function.");
    1750              :   }
    1751              : 
    1752            0 :   _info = (ml_info_s *) ml_info;
    1753              : 
    1754            0 :   iter = g_new0 (ml_info_iter_data_s, 1);
    1755            0 :   if (!iter) {
    1756            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1757              :         "Failed to allocate memory for the iteration. Out of memory?");
    1758              :   }
    1759              : 
    1760            0 :   iter->callback = cb;
    1761            0 :   iter->user_data = user_data;
    1762              : 
    1763            0 :   g_hash_table_foreach (_info->table, _ml_information_iter_internal, iter);
    1764            0 :   g_free (iter);
    1765              : 
    1766            0 :   return ML_ERROR_NONE;
    1767              : }
    1768              : 
    1769              : /**
    1770              :  * @brief Frees the given handle of a ml_information.
    1771              :  */
    1772              : int
    1773            0 : ml_information_destroy (ml_information_h information)
    1774              : {
    1775            0 :   check_feature_state (ML_FEATURE);
    1776              : 
    1777            0 :   if (!information) {
    1778            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1779              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1780              :   }
    1781              : 
    1782            0 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1783            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1784              :         "The parameter, 'information' is not a ml-information handle.");
    1785              : 
    1786            0 :   _ml_info_destroy (information);
    1787              : 
    1788            0 :   return ML_ERROR_NONE;
    1789              : }
    1790              : 
    1791              : /**
    1792              :  * @brief Gets the value corresponding to the given key in ml_information instance.
    1793              :  */
    1794              : int
    1795            0 : ml_information_get (ml_information_h information, const char *key, void **value)
    1796              : {
    1797            0 :   check_feature_state (ML_FEATURE);
    1798              : 
    1799            0 :   if (!information) {
    1800            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1801              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1802              :   }
    1803              : 
    1804            0 :   if (!key) {
    1805            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1806              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1807              :   }
    1808              : 
    1809            0 :   if (!value) {
    1810            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1811              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1812              :   }
    1813              : 
    1814            0 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1815            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1816              :         "The parameter, 'information' is not a ml-information handle.");
    1817              : 
    1818            0 :   return _ml_info_get_value ((ml_info_s *) information, key, value);
    1819              : }
    1820              : 
    1821              : /**
    1822              :  * @brief Creates an ml-information-list instance and returns the handle.
    1823              :  */
    1824              : int
    1825            0 : _ml_information_list_create (ml_information_list_h * list)
    1826              : {
    1827              :   ml_info_list_s *_info_list;
    1828              : 
    1829            0 :   check_feature_state (ML_FEATURE);
    1830              : 
    1831            0 :   if (!list)
    1832            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1833              :         "The parameter, 'list' is NULL. It should be a valid ml_information_list_h.");
    1834              : 
    1835            0 :   _info_list = g_try_new0 (ml_info_list_s, 1);
    1836            0 :   if (!_info_list) {
    1837            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1838              :         "Failed to allocate memory for ml_information_list_h. Out of memory?");
    1839              :   }
    1840              : 
    1841            0 :   _info_list->type = ML_INFO_TYPE_INFORMATION_LIST;
    1842              : 
    1843            0 :   *list = _info_list;
    1844            0 :   return ML_ERROR_NONE;
    1845              : }
    1846              : 
    1847              : /**
    1848              :  * @brief Adds an ml-information into ml-information-list.
    1849              :  */
    1850              : int
    1851            0 : _ml_information_list_add (ml_information_list_h list, ml_information_h info)
    1852              : {
    1853              :   ml_info_list_s *_info_list;
    1854              : 
    1855            0 :   check_feature_state (ML_FEATURE);
    1856              : 
    1857            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1858            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1859              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1860              :   }
    1861              : 
    1862            0 :   if (!_ml_info_is_valid (info, ML_INFO_TYPE_OPTION) &&
    1863            0 :       !_ml_info_is_valid (info, ML_INFO_TYPE_INFORMATION)) {
    1864            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1865              :         "The parameter, 'info' is invalid. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1866              :   }
    1867              : 
    1868            0 :   _info_list = (ml_info_list_s *) list;
    1869            0 :   _info_list->info = g_slist_append (_info_list->info, info);
    1870              : 
    1871            0 :   return ML_ERROR_NONE;
    1872              : }
    1873              : 
    1874              : /**
    1875              :  * @brief Destroys the ml-information-list instance.
    1876              :  */
    1877              : int
    1878            0 : ml_information_list_destroy (ml_information_list_h list)
    1879              : {
    1880              :   ml_info_list_s *_info_list;
    1881              : 
    1882            0 :   check_feature_state (ML_FEATURE);
    1883              : 
    1884            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1885            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1886              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1887              :   }
    1888              : 
    1889            0 :   _info_list = (ml_info_list_s *) list;
    1890            0 :   g_slist_free_full (_info_list->info, _ml_info_destroy);
    1891            0 :   g_free (_info_list);
    1892              : 
    1893            0 :   return ML_ERROR_NONE;
    1894              : }
    1895              : 
    1896              : /**
    1897              :  * @brief Gets the number of ml-information in ml-information-list instance.
    1898              :  */
    1899              : int
    1900            0 : ml_information_list_length (ml_information_list_h list, unsigned int *length)
    1901              : {
    1902              :   ml_info_list_s *_info_list;
    1903              : 
    1904            0 :   check_feature_state (ML_FEATURE);
    1905              : 
    1906            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1907            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1908              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1909              :   }
    1910              : 
    1911            0 :   if (!length) {
    1912            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1913              :         "The parameter, 'length' is NULL. It should be a valid unsigned int*");
    1914              :   }
    1915              : 
    1916            0 :   _info_list = (ml_info_list_s *) list;
    1917            0 :   *length = g_slist_length (_info_list->info);
    1918              : 
    1919            0 :   return ML_ERROR_NONE;
    1920              : }
    1921              : 
    1922              : /**
    1923              :  * @brief Gets a ml-information in ml-information-list instance with given index.
    1924              :  */
    1925              : int
    1926            0 : ml_information_list_get (ml_information_list_h list, unsigned int index,
    1927              :     ml_information_h * information)
    1928              : {
    1929              :   ml_info_list_s *_info_list;
    1930              : 
    1931            0 :   check_feature_state (ML_FEATURE);
    1932              : 
    1933            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1934            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1935              :         "The parameter, 'list' is NULL. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1936              :   }
    1937              : 
    1938            0 :   if (!information) {
    1939            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1940              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h*");
    1941              :   }
    1942              : 
    1943            0 :   _info_list = (ml_info_list_s *) list;
    1944            0 :   *information = g_slist_nth_data (_info_list->info, index);
    1945              : 
    1946            0 :   if (*information == NULL) {
    1947            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1948              :         "The parameter, 'index' is invalid. It should be less than the length of ml_information_list_h.");
    1949              :   }
    1950              : 
    1951            0 :   return ML_ERROR_NONE;
    1952              : }
        

Generated by: LCOV version 2.0-1