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 nnstreamer/api#90009cb64c1abde99495401157da07dd5a7fbd7e Lines: 87.1 % 776 676
Test Date: 2025-10-23 05:29:07 Functions: 96.7 % 60 58

            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            1 : ml_api_get_version (unsigned int *major, unsigned int *minor,
      76              :     unsigned int *micro)
      77              : {
      78            1 :   if (major)
      79            1 :     *major = VERSION_MAJOR;
      80            1 :   if (minor)
      81            1 :     *minor = VERSION_MINOR;
      82            1 :   if (micro)
      83            1 :     *micro = VERSION_MICRO;
      84            1 : }
      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          423 : convert_tensor_type_from (ml_tensor_type_e type)
      93              : {
      94          423 :   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          423 :   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          640 : convert_ml_tensor_type_from (tensor_type type)
     111              : {
     112          640 :   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          640 :   return (ml_tensor_type_e) type;
     119              : }
     120              : 
     121              : /**
     122              :  * @brief Gets the version string of machine-learning API.
     123              :  */
     124              : char *
     125            1 : ml_api_get_version_string (void)
     126              : {
     127            1 :   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        18739 : _ml_tensors_info_create_internal (ml_tensors_info_h * info, bool extended)
     135              : {
     136              :   ml_tensors_info_s *tensors_info;
     137              : 
     138        18739 :   check_feature_state (ML_FEATURE);
     139              : 
     140        18739 :   if (!info)
     141            2 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     142              :         "The parameter, info, is NULL. Provide a valid pointer.");
     143              : 
     144        18737 :   *info = tensors_info = g_new0 (ml_tensors_info_s, 1);
     145        18737 :   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        18737 :   g_mutex_init (&tensors_info->lock);
     150        18737 :   tensors_info->is_extended = extended;
     151              : 
     152              :   /* init tensors info struct */
     153        18737 :   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         6349 : _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         6349 :   if (!in || !out)
     167            0 :     return ML_ERROR_INVALID_PARAMETER;
     168              : 
     169         6349 :   _info = (ml_tensors_info_s *) in;
     170              : 
     171         6349 :   if (_info->is_extended)
     172            7 :     status = ml_tensors_info_create_extended (out);
     173              :   else
     174         6342 :     status = ml_tensors_info_create (out);
     175              : 
     176         6349 :   if (status == ML_ERROR_NONE)
     177         6349 :     status = ml_tensors_info_clone (*out, in);
     178              : 
     179         6349 :   return status;
     180              : }
     181              : 
     182              : /**
     183              :  * @brief Allocates a tensors information handle with default value.
     184              :  */
     185              : int
     186        18704 : ml_tensors_info_create (ml_tensors_info_h * info)
     187              : {
     188        18704 :   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           35 : ml_tensors_info_create_extended (ml_tensors_info_h * info)
     196              : {
     197           35 :   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        18711 : ml_tensors_info_destroy (ml_tensors_info_h info)
     205              : {
     206              :   ml_tensors_info_s *tensors_info;
     207              : 
     208        18711 :   check_feature_state (ML_FEATURE);
     209              : 
     210        18711 :   tensors_info = (ml_tensors_info_s *) info;
     211              : 
     212        18711 :   if (!tensors_info)
     213            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     214              :         "The parameter, info, is NULL. Provide a valid pointer.");
     215              : 
     216        18710 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     217        18710 :   _ml_tensors_info_free (tensors_info);
     218        18710 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     219              : 
     220        18710 :   g_mutex_clear (&tensors_info->lock);
     221        18710 :   g_free (tensors_info);
     222              : 
     223        18710 :   return ML_ERROR_NONE;
     224              : }
     225              : 
     226              : /**
     227              :  * @brief Validates the given tensors info is valid.
     228              :  */
     229              : int
     230         6181 : ml_tensors_info_validate (const ml_tensors_info_h info, bool *valid)
     231              : {
     232              :   ml_tensors_info_s *tensors_info;
     233              : 
     234         6181 :   check_feature_state (ML_FEATURE);
     235              : 
     236         6181 :   if (!valid)
     237            1 :     _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         6180 :   tensors_info = (ml_tensors_info_s *) info;
     241              : 
     242         6180 :   if (!tensors_info)
     243            3 :     _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         6177 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     247         6177 :   *valid = gst_tensors_info_validate (&tensors_info->info);
     248         6177 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     249              : 
     250         6177 :   return ML_ERROR_NONE;
     251              : }
     252              : 
     253              : /**
     254              :  * @brief Compares the given tensors information.
     255              :  */
     256              : int
     257           68 : _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           68 :   check_feature_state (ML_FEATURE);
     263              : 
     264           68 :   if (info1 == NULL)
     265            1 :     _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           67 :   if (info2 == NULL)
     268            1 :     _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           66 :   if (equal == NULL)
     271            1 :     _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           65 :   i1 = (ml_tensors_info_s *) info1;
     275           65 :   G_LOCK_UNLESS_NOLOCK (*i1);
     276           65 :   i2 = (ml_tensors_info_s *) info2;
     277           65 :   G_LOCK_UNLESS_NOLOCK (*i2);
     278              : 
     279           65 :   *equal = gst_tensors_info_is_equal (&i1->info, &i2->info);
     280              : 
     281           65 :   G_UNLOCK_UNLESS_NOLOCK (*i2);
     282           65 :   G_UNLOCK_UNLESS_NOLOCK (*i1);
     283           65 :   return ML_ERROR_NONE;
     284              : }
     285              : 
     286              : /**
     287              :  * @brief Sets the number of tensors with given handle of tensors information.
     288              :  */
     289              : int
     290          137 : ml_tensors_info_set_count (ml_tensors_info_h info, unsigned int count)
     291              : {
     292              :   ml_tensors_info_s *tensors_info;
     293              : 
     294          137 :   check_feature_state (ML_FEATURE);
     295              : 
     296          137 :   if (!info)
     297            1 :     _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          136 :   if (count > ML_TENSOR_SIZE_LIMIT || count == 0)
     300            2 :     _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          134 :   tensors_info = (ml_tensors_info_s *) info;
     305              : 
     306              :   /* This is atomic. No need for locks */
     307          134 :   tensors_info->info.num_tensors = count;
     308              : 
     309          134 :   return ML_ERROR_NONE;
     310              : }
     311              : 
     312              : /**
     313              :  * @brief Gets the number of tensors with given handle of tensors information.
     314              :  */
     315              : int
     316           82 : ml_tensors_info_get_count (ml_tensors_info_h info, unsigned int *count)
     317              : {
     318              :   ml_tensors_info_s *tensors_info;
     319              : 
     320           82 :   check_feature_state (ML_FEATURE);
     321              : 
     322           82 :   if (!info)
     323            1 :     _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           81 :   if (!count)
     326            1 :     _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           80 :   tensors_info = (ml_tensors_info_s *) info;
     330              :   /* This is atomic. No need for locks */
     331           80 :   *count = tensors_info->info.num_tensors;
     332              : 
     333           80 :   return ML_ERROR_NONE;
     334              : }
     335              : 
     336              : /**
     337              :  * @brief Sets the tensor name with given handle of tensors information.
     338              :  */
     339              : int
     340           10 : 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           10 :   check_feature_state (ML_FEATURE);
     347              : 
     348           10 :   if (!info)
     349            1 :     _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            9 :   tensors_info = (ml_tensors_info_s *) info;
     353            9 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     354              : 
     355            9 :   if (tensors_info->info.num_tensors <= index) {
     356            1 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     357            1 :     _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            8 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     363            8 :   if (!_info) {
     364            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     365            0 :     return ML_ERROR_INVALID_PARAMETER;
     366              :   }
     367              : 
     368            8 :   g_free (_info->name);
     369            8 :   _info->name = g_strdup (name);
     370              : 
     371            8 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     372            8 :   return ML_ERROR_NONE;
     373              : }
     374              : 
     375              : /**
     376              :  * @brief Gets the tensor name with given handle of tensors information.
     377              :  */
     378              : int
     379           18 : 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           18 :   check_feature_state (ML_FEATURE);
     386              : 
     387           18 :   if (!info)
     388            1 :     _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           17 :   if (!name)
     391            1 :     _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           16 :   tensors_info = (ml_tensors_info_s *) info;
     395           16 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     396              : 
     397           16 :   if (tensors_info->info.num_tensors <= index) {
     398            2 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     399            2 :     _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           14 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     405           14 :   if (!_info) {
     406            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     407            0 :     return ML_ERROR_INVALID_PARAMETER;
     408              :   }
     409              : 
     410           14 :   *name = g_strdup (_info->name);
     411              : 
     412           14 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     413           14 :   return ML_ERROR_NONE;
     414              : }
     415              : 
     416              : /**
     417              :  * @brief Sets the tensor type with given handle of tensors information.
     418              :  */
     419              : int
     420          429 : 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          429 :   check_feature_state (ML_FEATURE);
     427              : 
     428          429 :   if (!info)
     429            1 :     _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          428 :   if (type >= ML_TENSOR_TYPE_UNKNOWN || type < 0)
     433            2 :     _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          426 :   if (type == ML_TENSOR_TYPE_FLOAT16)
     439            1 :     _ml_error_report_return (ML_ERROR_NOT_SUPPORTED,
     440              :         "Float16 (IEEE 754) is not supported by the machine (or the compiler or your build configuration). You cannot configure ml_tensors_info instance with Float16 type.");
     441              : #endif
     442              :   /** @todo add BFLOAT16 when nnstreamer is ready for it. */
     443              : 
     444          425 :   tensors_info = (ml_tensors_info_s *) info;
     445          425 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     446              : 
     447          425 :   if (tensors_info->info.num_tensors <= index) {
     448            2 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     449            2 :     _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          423 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     455          423 :   if (!_info) {
     456            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     457            0 :     return ML_ERROR_INVALID_PARAMETER;
     458              :   }
     459              : 
     460          423 :   _info->type = convert_tensor_type_from (type);
     461              : 
     462          423 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     463          423 :   return ML_ERROR_NONE;
     464              : }
     465              : 
     466              : /**
     467              :  * @brief Gets the tensor type with given handle of tensors information.
     468              :  */
     469              : int
     470          644 : 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          644 :   check_feature_state (ML_FEATURE);
     477              : 
     478          644 :   if (!info)
     479            1 :     _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          643 :   if (!type)
     482            1 :     _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          642 :   tensors_info = (ml_tensors_info_s *) info;
     486          642 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     487              : 
     488          642 :   if (tensors_info->info.num_tensors <= index) {
     489            2 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     490            2 :     _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          640 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     496          640 :   if (!_info) {
     497            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     498            0 :     return ML_ERROR_INVALID_PARAMETER;
     499              :   }
     500              : 
     501          640 :   *type = convert_ml_tensor_type_from (_info->type);
     502              : 
     503          640 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     504          640 :   return ML_ERROR_NONE;
     505              : }
     506              : 
     507              : /**
     508              :  * @brief Sets the tensor dimension with given handle of tensors information.
     509              :  */
     510              : int
     511          422 : 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          422 :   check_feature_state (ML_FEATURE);
     519              : 
     520          422 :   if (!info)
     521            1 :     _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          421 :   tensors_info = (ml_tensors_info_s *) info;
     525          421 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     526              : 
     527          421 :   if (tensors_info->info.num_tensors <= index) {
     528            2 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     529            2 :     _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          838 :   max_rank = tensors_info->is_extended ?
     540          419 :       ML_TENSOR_RANK_LIMIT : ML_TENSOR_RANK_LIMIT_PREV;
     541          419 :   rank = max_rank + 1;
     542         2234 :   for (i = 0; i < max_rank; i++) {
     543         1819 :     if (dimension[i] == 0) {
     544           82 :       if (rank > max_rank)
     545           21 :         rank = i;
     546              :     }
     547              : 
     548         1819 :     if (rank == 0 || (i > rank && dimension[i] > 0)) {
     549            4 :       G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     550            4 :       _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          415 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     556          415 :   if (!_info) {
     557            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     558            0 :     return ML_ERROR_INVALID_PARAMETER;
     559              :   }
     560              : 
     561         2075 :   for (i = 0; i < ML_TENSOR_RANK_LIMIT_PREV; i++) {
     562         1660 :     _info->dimension[i] = dimension[i];
     563              :   }
     564              : 
     565         5395 :   for (i = ML_TENSOR_RANK_LIMIT_PREV; i < ML_TENSOR_RANK_LIMIT; i++) {
     566         4980 :     _info->dimension[i] = (tensors_info->is_extended ? dimension[i] : 0);
     567              :   }
     568              : 
     569          415 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     570          415 :   return ML_ERROR_NONE;
     571              : }
     572              : 
     573              : /**
     574              :  * @brief Gets the tensor dimension with given handle of tensors information.
     575              :  */
     576              : int
     577         1119 : 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         1119 :   guint i, valid_rank = ML_TENSOR_RANK_LIMIT;
     583              : 
     584         1119 :   check_feature_state (ML_FEATURE);
     585              : 
     586         1119 :   if (!info)
     587            1 :     _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         1118 :   tensors_info = (ml_tensors_info_s *) info;
     591         1118 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     592              : 
     593         1118 :   if (tensors_info->info.num_tensors <= index) {
     594            2 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     595            2 :     _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         1116 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     601         1116 :   if (!_info) {
     602            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     603            0 :     return ML_ERROR_INVALID_PARAMETER;
     604              :   }
     605              : 
     606         1116 :   if (!tensors_info->is_extended)
     607         1108 :     valid_rank = ML_TENSOR_RANK_LIMIT_PREV;
     608              : 
     609         5676 :   for (i = 0; i < valid_rank; i++) {
     610         4560 :     dimension[i] = _info->dimension[i];
     611              :   }
     612              : 
     613        14412 :   for (; i < ML_TENSOR_RANK_LIMIT; i++)
     614        13296 :     dimension[i] = 0;
     615              : 
     616         1116 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     617         1116 :   return ML_ERROR_NONE;
     618              : }
     619              : 
     620              : /**
     621              :  * @brief Gets the byte size of the given handle of tensors information.
     622              :  */
     623              : int
     624           25 : 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           25 :   check_feature_state (ML_FEATURE);
     630              : 
     631           25 :   if (!info)
     632            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     633              :         "The parameter, info, is NULL. Provide a valid pointer.");
     634           24 :   if (!data_size)
     635            1 :     _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           23 :   tensors_info = (ml_tensors_info_s *) info;
     639           23 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     640              : 
     641              :   /* init 0 */
     642           23 :   *data_size = 0;
     643              : 
     644           23 :   if (index >= 0 && tensors_info->info.num_tensors <= index) {
     645            2 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     646            2 :     _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           21 :   *data_size = gst_tensors_info_get_size (&tensors_info->info, index);
     652              : 
     653           21 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     654           21 :   return ML_ERROR_NONE;
     655              : }
     656              : 
     657              : /**
     658              :  * @brief Initializes the tensors information with default value.
     659              :  */
     660              : int
     661        18738 : _ml_tensors_info_initialize (ml_tensors_info_s * info)
     662              : {
     663        18738 :   if (!info)
     664            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     665              :         "The parameter, info, is NULL. Provide a valid pointer.");
     666              : 
     667        18737 :   gst_tensors_info_init (&info->info);
     668              : 
     669        18737 :   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        18750 : _ml_tensors_info_free (ml_tensors_info_s * info)
     678              : {
     679        18750 :   if (!info)
     680            0 :     return;
     681              : 
     682        18750 :   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        12270 : _ml_tensors_data_destroy_internal (ml_tensors_data_h data, gboolean free_data)
     693              : {
     694        12270 :   int status = ML_ERROR_NONE;
     695              :   ml_tensors_data_s *_data;
     696              :   guint i;
     697              : 
     698        12270 :   if (data == NULL)
     699           19 :     _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        12251 :   _data = (ml_tensors_data_s *) data;
     703        12251 :   G_LOCK_UNLESS_NOLOCK (*_data);
     704              : 
     705        12251 :   if (free_data) {
     706          449 :     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       115393 :       for (i = 0; i < ML_TENSOR_SIZE_LIMIT; i++) {
     716       114944 :         if (_data->tensors[i].data) {
     717          673 :           g_free (_data->tensors[i].data);
     718          673 :           _data->tensors[i].data = NULL;
     719              :         }
     720              :       }
     721              :     }
     722              :   }
     723              : 
     724        12251 :   if (_data->info)
     725        12251 :     ml_tensors_info_destroy (_data->info);
     726              : 
     727        12251 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     728        12251 :   g_mutex_clear (&_data->lock);
     729        12251 :   g_free (_data);
     730        12251 :   return status;
     731              : }
     732              : 
     733              : /**
     734              :  * @brief Frees the tensors data pointer.
     735              :  * @note This does not touch the lock
     736              :  */
     737              : int
     738          468 : ml_tensors_data_destroy (ml_tensors_data_h data)
     739              : {
     740              :   int ret;
     741          468 :   check_feature_state (ML_FEATURE);
     742          468 :   ret = _ml_tensors_data_destroy_internal (data, TRUE);
     743          468 :   if (ret != ML_ERROR_NONE)
     744           19 :     _ml_error_report_return_continue (ret,
     745              :         "Call to _ml_tensors_data_destroy_internal failed with %d", ret);
     746          449 :   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        12274 : _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        12274 :   int status = ML_ERROR_NONE;
     761              : 
     762        12274 :   check_feature_state (ML_FEATURE);
     763              : 
     764        12274 :   if (data == NULL)
     765            1 :     _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        12273 :   *data = NULL;
     770              : 
     771        12273 :   _data = g_new0 (ml_tensors_data_s, 1);
     772        12273 :   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        12273 :   g_mutex_init (&_data->lock);
     777              : 
     778        12273 :   _info = (ml_tensors_info_s *) info;
     779        12273 :   if (_info != NULL) {
     780         6340 :     status = _ml_tensors_info_create_from (info, &_data->info);
     781         6340 :     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         6340 :     G_LOCK_UNLESS_NOLOCK (*_info);
     788         6340 :     _data->num_tensors = _info->info.num_tensors;
     789        13120 :     for (i = 0; i < _data->num_tensors; i++) {
     790         6780 :       _data->tensors[i].size = gst_tensors_info_get_size (&_info->info, i);
     791         6780 :       _data->tensors[i].data = NULL;
     792              :     }
     793         6340 :     G_UNLOCK_UNLESS_NOLOCK (*_info);
     794              :   }
     795              : 
     796         5933 : error:
     797        12273 :   if (status == ML_ERROR_NONE) {
     798        12273 :     *data = _data;
     799              :   } else {
     800            0 :     _ml_tensors_data_destroy_internal (_data, FALSE);
     801              :   }
     802              : 
     803        12273 :   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           79 : _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          158 :   check_feature_state (ML_FEATURE);
     818              : 
     819           79 :   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           79 :   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           79 :   status = _ml_tensors_data_create_no_alloc (data_src->info,
     827              :       (ml_tensors_data_h *) & _data);
     828           79 :   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           79 :   G_LOCK_UNLESS_NOLOCK (*_data);
     834              : 
     835           79 :   _data->num_tensors = data_src->num_tensors;
     836           79 :   memcpy (_data->tensors, data_src->tensors,
     837           79 :       sizeof (GstTensorMemory) * data_src->num_tensors);
     838              : 
     839           79 :   *data = _data;
     840           79 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     841           79 :   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         6306 : _ml_tensor_data_alloc (ml_tensors_data_s * data, guint index, const size_t size)
     850              : {
     851         6306 :   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         6306 :   data->tensors[index].size = size;
     856         6306 :   data->tensors[index].data = g_malloc0 (size);
     857         6306 :   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         6306 :   return ML_ERROR_NONE;
     862              : }
     863              : 
     864              : /**
     865              :  * @brief Copies the tensor data frame.
     866              :  */
     867              : int
     868          156 : ml_tensors_data_clone (const ml_tensors_data_h in, ml_tensors_data_h * out)
     869              : {
     870              :   int status;
     871              :   unsigned int i;
     872          156 :   ml_tensors_data_s *_in, *_out = NULL;
     873              : 
     874          156 :   check_feature_state (ML_FEATURE);
     875              : 
     876          156 :   if (in == NULL)
     877            1 :     _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          155 :   if (out == NULL)
     881            1 :     _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          154 :   _in = (ml_tensors_data_s *) in;
     885          154 :   G_LOCK_UNLESS_NOLOCK (*_in);
     886              : 
     887          154 :   status = ml_tensors_data_create (_in->info, out);
     888          154 :   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          154 :   _out = (ml_tensors_data_s *) (*out);
     894              : 
     895          464 :   for (i = 0; i < _out->num_tensors; ++i) {
     896          310 :     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          310 :     memcpy (_out->tensors[i].data, _in->tensors[i].data, _in->tensors[i].size);
     908              :   }
     909              : 
     910          154 : error:
     911          154 :   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          154 :   G_UNLOCK_UNLESS_NOLOCK (*_in);
     918          154 :   return status;
     919              : }
     920              : 
     921              : /**
     922              :  * @brief Gets the tensors information of given tensor data frame.
     923              :  */
     924              : int
     925            3 : 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            3 :   check_feature_state (ML_FEATURE);
     932              : 
     933            3 :   if (data == NULL) {
     934            1 :     _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            2 :   if (info == NULL) {
     939            1 :     _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            1 :   _data = (ml_tensors_data_s *) data;
     944            1 :   G_LOCK_UNLESS_NOLOCK (*_data);
     945              : 
     946            1 :   status = _ml_tensors_info_create_from (_data->info, info);
     947            1 :   if (status != ML_ERROR_NONE) {
     948            0 :     _ml_error_report_continue
     949              :         ("Failed to get the tensor information from data handle.");
     950              :   }
     951              : 
     952            1 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     953            1 :   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         6087 : ml_tensors_data_create (const ml_tensors_info_h info, ml_tensors_data_h * data)
     961              : {
     962         6087 :   int status = ML_ERROR_NONE;
     963         6087 :   ml_tensors_info_s *_info = NULL;
     964         6087 :   ml_tensors_data_s *_data = NULL;
     965              :   guint i;
     966              :   bool valid;
     967              : 
     968        12174 :   check_feature_state (ML_FEATURE);
     969              : 
     970         6087 :   if (info == NULL)
     971            1 :     _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         6086 :   if (data == NULL)
     974            1 :     _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         6085 :   status = ml_tensors_info_validate (info, &valid);
     978         6085 :   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         6085 :   if (!valid)
     982            1 :     _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         6084 :       _ml_tensors_data_create_no_alloc (info, (ml_tensors_data_h *) & _data);
     987              : 
     988         6084 :   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         6084 :   _info = (ml_tensors_info_s *) info;
     995         6084 :   if (_info->info.format == _NNS_TENSOR_FORMAT_STATIC) {
     996        12390 :     for (i = 0; i < _data->num_tensors; i++) {
     997         6306 :       status = _ml_tensor_data_alloc (_data, i, _data->tensors[i].size);
     998         6306 :       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         6084 : error:
    1007         6084 :   if (status == ML_ERROR_NONE) {
    1008         6084 :     *data = _data;
    1009              :   } else {
    1010            0 :     _ml_tensors_data_destroy_internal (_data, TRUE);
    1011              :   }
    1012              : 
    1013         6084 :   return status;
    1014              : }
    1015              : 
    1016              : /**
    1017              :  * @brief Gets a tensor data of given handle.
    1018              :  */
    1019              : int
    1020          770 : 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          770 :   int status = ML_ERROR_NONE;
    1025              : 
    1026          770 :   check_feature_state (ML_FEATURE);
    1027              : 
    1028          770 :   if (data == NULL)
    1029            1 :     _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          769 :   if (raw_data == NULL)
    1032            1 :     _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          768 :   if (data_size == NULL)
    1035            1 :     _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          767 :   _data = (ml_tensors_data_s *) data;
    1039          767 :   G_LOCK_UNLESS_NOLOCK (*_data);
    1040              : 
    1041          767 :   if (_data->num_tensors <= index) {
    1042            2 :     _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            2 :     status = ML_ERROR_INVALID_PARAMETER;
    1046            2 :     goto report;
    1047              :   }
    1048              : 
    1049          765 :   *raw_data = _data->tensors[index].data;
    1050          765 :   *data_size = _data->tensors[index].size;
    1051              : 
    1052          767 : report:
    1053          767 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1054          767 :   return status;
    1055              : }
    1056              : 
    1057              : /**
    1058              :  * @brief Copies a tensor data to given handle.
    1059              :  */
    1060              : int
    1061          281 : 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          281 :   ml_tensors_info_s *_info = NULL;
    1065              :   ml_tensors_data_s *_data;
    1066          281 :   int status = ML_ERROR_NONE;
    1067              : 
    1068          281 :   check_feature_state (ML_FEATURE);
    1069              : 
    1070          281 :   if (data == NULL)
    1071            1 :     _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          280 :   if (raw_data == NULL)
    1074            1 :     _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          279 :   _data = (ml_tensors_data_s *) data;
    1079          279 :   G_LOCK_UNLESS_NOLOCK (*_data);
    1080              : 
    1081          279 :   if (_data->num_tensors <= index) {
    1082            1 :     _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            1 :     status = ML_ERROR_INVALID_PARAMETER;
    1086            1 :     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          278 :   _info = (ml_tensors_info_s *) _data->info;
    1098          278 :   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          278 :   if (data_size <= 0 || _data->tensors[index].size < data_size) {
    1114            2 :     _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            2 :     status = ML_ERROR_INVALID_PARAMETER;
    1118            2 :     goto report;
    1119              :   }
    1120              : 
    1121          276 :   if (_data->tensors[index].data != raw_data)
    1122          273 :     memcpy (_data->tensors[index].data, raw_data, data_size);
    1123              : 
    1124            3 : report:
    1125          279 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1126          279 :   return status;
    1127              : }
    1128              : 
    1129              : /**
    1130              :  * @brief Copies tensor meta info.
    1131              :  */
    1132              : int
    1133         6362 : 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         6362 :   int status = ML_ERROR_NONE;
    1137              : 
    1138         6362 :   check_feature_state (ML_FEATURE);
    1139              : 
    1140         6362 :   dest_info = (ml_tensors_info_s *) dest;
    1141         6362 :   src_info = (ml_tensors_info_s *) src;
    1142              : 
    1143         6362 :   if (!dest_info)
    1144            1 :     _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         6361 :   if (!src_info)
    1147            1 :     _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         6360 :   G_LOCK_UNLESS_NOLOCK (*dest_info);
    1151         6360 :   G_LOCK_UNLESS_NOLOCK (*src_info);
    1152              : 
    1153         6360 :   if (gst_tensors_info_validate (&src_info->info)) {
    1154         6360 :     dest_info->is_extended = src_info->is_extended;
    1155         6360 :     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         6360 :   G_UNLOCK_UNLESS_NOLOCK (*src_info);
    1164         6360 :   G_UNLOCK_UNLESS_NOLOCK (*dest_info);
    1165              : 
    1166         6360 :   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           15 : _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           15 :   guint changed = 0;
    1187              :   gsize len;
    1188              : 
    1189           15 :   g_return_val_if_fail (source, NULL);
    1190           15 :   g_return_val_if_fail (what && to, source);
    1191              : 
    1192           15 :   len = strlen (what);
    1193           15 :   start = source;
    1194              : 
    1195           15 :   builder = g_string_new (NULL);
    1196           57 :   while ((pos = g_strstr_len (start, -1, what)) != NULL) {
    1197           42 :     gboolean skip = FALSE;
    1198              : 
    1199           42 :     if (delimiters) {
    1200              :       const gchar *s;
    1201              :       gchar *prev, *next;
    1202              :       gboolean prev_split, next_split;
    1203              : 
    1204           22 :       prev = next = NULL;
    1205           22 :       prev_split = next_split = FALSE;
    1206              : 
    1207           22 :       if (pos != source)
    1208           18 :         prev = pos - 1;
    1209           22 :       if (*(pos + len) != '\0')
    1210           19 :         next = pos + len;
    1211              : 
    1212           46 :       for (s = delimiters; *s != '\0'; ++s) {
    1213           34 :         if (!prev || *s == *prev)
    1214           16 :           prev_split = TRUE;
    1215           34 :         if (!next || *s == *next)
    1216           15 :           next_split = TRUE;
    1217           34 :         if (prev_split && next_split)
    1218           10 :           break;
    1219              :       }
    1220              : 
    1221           22 :       if (!prev_split || !next_split)
    1222           12 :         skip = TRUE;
    1223              :     }
    1224              : 
    1225           42 :     builder = g_string_append_len (builder, start, pos - start);
    1226              : 
    1227              :     /* replace string if found */
    1228           42 :     if (skip)
    1229           24 :       builder = g_string_append_len (builder, pos, len);
    1230              :     else
    1231           30 :       builder = g_string_append (builder, to);
    1232              : 
    1233           42 :     start = pos + len;
    1234           42 :     if (!skip)
    1235           30 :       changed++;
    1236              :   }
    1237              : 
    1238              :   /* append remains */
    1239           15 :   builder = g_string_append (builder, start);
    1240           15 :   result = g_string_free (builder, FALSE);
    1241              : 
    1242           15 :   if (count)
    1243            9 :     *count = changed;
    1244              : 
    1245           15 :   g_free (source);
    1246           15 :   return result;
    1247              : }
    1248              : 
    1249              : /**
    1250              :  * @brief Converts predefined entity.
    1251              :  */
    1252              : gchar *
    1253          343 : _ml_convert_predefined_entity (const gchar * str)
    1254              : {
    1255          343 :   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          343 :   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         1018 : _ml_error_report_ (const char *fmt, ...)
    1307              : {
    1308              :   int n;
    1309              :   va_list arg_ptr;
    1310         1018 :   G_LOCK (errlock);
    1311              : 
    1312         1018 :   va_start (arg_ptr, fmt);
    1313         1018 :   n = vsnprintf (errormsg, _ML_ERRORMSG_LENGTH, fmt, arg_ptr);
    1314         1018 :   va_end (arg_ptr);
    1315              : 
    1316         1018 :   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         1018 :   _ml_loge ("%s", errormsg);
    1323              : 
    1324         1018 :   reported = 0;
    1325              : 
    1326         1018 :   G_UNLOCK (errlock);
    1327         1018 : }
    1328              : 
    1329              : /**
    1330              :  * @brief Internal interface to write messages for ml_error(), relaying previously reported errors.
    1331              :  */
    1332              : void
    1333           44 : _ml_error_report_continue_ (const char *fmt, ...)
    1334              : {
    1335           44 :   size_t cursor = 0;
    1336              :   va_list arg_ptr;
    1337              :   char buf[_ML_ERRORMSG_LENGTH];
    1338           44 :   G_LOCK (errlock);
    1339              : 
    1340              :   /* Check if there is a message to relay */
    1341           44 :   if (reported == 0) {
    1342           44 :     cursor = strlen (errormsg);
    1343           44 :     if (cursor < (_ML_ERRORMSG_LENGTH - 1)) {
    1344           44 :       errormsg[cursor] = '\n';
    1345           44 :       errormsg[cursor + 1] = '\0';
    1346           44 :       cursor++;
    1347              :     }
    1348              :   } else {
    1349            0 :     errormsg[0] = '\0';
    1350              :   }
    1351              : 
    1352           44 :   va_start (arg_ptr, fmt);
    1353           44 :   vsnprintf (buf, _ML_ERRORMSG_LENGTH - 1, fmt, arg_ptr);
    1354           44 :   _ml_loge ("%s", buf);
    1355              : 
    1356           44 :   memcpy (errormsg + cursor, buf, _ML_ERRORMSG_LENGTH - strlen (errormsg) - 1);
    1357           44 :   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           44 :   va_end (arg_ptr);
    1364              : 
    1365           44 :   errormsg[_ML_ERRORMSG_LENGTH - 1] = '\0';
    1366           44 :   reported = 0;
    1367           44 :   G_UNLOCK (errlock);
    1368           44 : }
    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         1506 : _ml_info_is_valid (gpointer handle, ml_info_type_e expected)
    1397              : {
    1398              :   ml_info_type_e current;
    1399              : 
    1400         1506 :   if (!handle)
    1401            7 :     return false;
    1402              : 
    1403              :   /* The first field should be an enum value of ml_info_type_e. */
    1404         1499 :   current = *((ml_info_type_e *) handle);
    1405         1499 :   if (current != expected)
    1406           14 :     return false;
    1407              : 
    1408         1485 :   switch (current) {
    1409         1464 :     case ML_INFO_TYPE_OPTION:
    1410              :     case ML_INFO_TYPE_INFORMATION:
    1411              :     {
    1412         1464 :       ml_info_s *_info = (ml_info_s *) handle;
    1413              : 
    1414         1464 :       if (!_info->table)
    1415            0 :         return false;
    1416              : 
    1417         1464 :       break;
    1418              :     }
    1419           21 :     case ML_INFO_TYPE_INFORMATION_LIST:
    1420           21 :       break;
    1421            0 :     default:
    1422              :       /* Unknown type */
    1423            0 :       return false;
    1424              :   }
    1425              : 
    1426         1485 :   return true;
    1427              : }
    1428              : 
    1429              : /**
    1430              :  * @brief Internal function for destroy value of option table
    1431              :  */
    1432              : static void
    1433          410 : _ml_info_value_free (gpointer data)
    1434              : {
    1435              :   ml_info_value_s *_value;
    1436              : 
    1437          410 :   _value = (ml_info_value_s *) data;
    1438          410 :   if (_value) {
    1439          410 :     if (_value->destroy)
    1440          347 :       _value->destroy (_value->value);
    1441          410 :     g_free (_value);
    1442              :   }
    1443          410 : }
    1444              : 
    1445              : /**
    1446              :  * @brief Internal function for create ml_info
    1447              :  */
    1448              : static ml_info_s *
    1449          250 : _ml_info_create (ml_info_type_e type)
    1450              : {
    1451              :   ml_info_s *info;
    1452              : 
    1453          250 :   info = g_new0 (ml_info_s, 1);
    1454          250 :   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          250 :   info->type = type;
    1461          250 :   info->table =
    1462          250 :       g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
    1463              :       _ml_info_value_free);
    1464          250 :   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          250 :   return info;
    1472              : }
    1473              : 
    1474              : /**
    1475              :  * @brief Internal function for destroy ml_info
    1476              :  */
    1477              : static void
    1478          246 : _ml_info_destroy (gpointer data)
    1479              : {
    1480          246 :   ml_info_s *info = (ml_info_s *) data;
    1481              : 
    1482          246 :   if (!info)
    1483            0 :     return;
    1484              : 
    1485          246 :   info->type = ML_INFO_TYPE_UNKNOWN;
    1486              : 
    1487          246 :   if (info->table) {
    1488          246 :     g_hash_table_destroy (info->table);
    1489          246 :     info->table = NULL;
    1490              :   }
    1491              : 
    1492          246 :   g_free (info);
    1493          246 :   return;
    1494              : }
    1495              : 
    1496              : /**
    1497              :  * @brief Internal function for set value of given ml_info
    1498              :  */
    1499              : static int
    1500          415 : _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          415 :   if (!STR_IS_VALID (key))
    1506            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1507              :         "The parameter, 'key' is invalid. It should be a valid string.");
    1508              : 
    1509          414 :   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          414 :   info_value = g_new0 (ml_info_value_s, 1);
    1514          414 :   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          414 :   info_value->value = value;
    1519          414 :   info_value->destroy = destroy;
    1520          414 :   g_hash_table_insert (info->table, g_strdup (key), (gpointer) info_value);
    1521              : 
    1522          414 :   return ML_ERROR_NONE;
    1523              : }
    1524              : 
    1525              : /**
    1526              :  * @brief Internal function for get value of given ml_info
    1527              :  */
    1528              : static int
    1529          801 : _ml_info_get_value (ml_info_s * info, const char *key, void **value)
    1530              : {
    1531              :   ml_info_value_s *info_value;
    1532              : 
    1533          801 :   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          801 :   info_value = g_hash_table_lookup (info->table, key);
    1538          801 :   if (!info_value) {
    1539          462 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1540              :         "Failed to find a value of key '%s', invalid key string?", key);
    1541              :   }
    1542              : 
    1543          339 :   *value = info_value->value;
    1544              : 
    1545          339 :   return ML_ERROR_NONE;
    1546              : }
    1547              : 
    1548              : /**
    1549              :  * @brief Creates an option and returns the instance a handle.
    1550              :  */
    1551              : int
    1552          194 : ml_option_create (ml_option_h * option)
    1553              : {
    1554          194 :   ml_info_s *_option = NULL;
    1555              : 
    1556          194 :   check_feature_state (ML_FEATURE);
    1557              : 
    1558          194 :   if (!option) {
    1559            1 :     _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          193 :   _option = _ml_info_create (ML_INFO_TYPE_OPTION);
    1564          193 :   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          193 :   *option = _option;
    1569          193 :   return ML_ERROR_NONE;
    1570              : }
    1571              : 
    1572              : /**
    1573              :  * @brief Frees the given handle of a ml_option.
    1574              :  */
    1575              : int
    1576          191 : ml_option_destroy (ml_option_h option)
    1577              : {
    1578          191 :   check_feature_state (ML_FEATURE);
    1579              : 
    1580          191 :   if (!option) {
    1581            1 :     _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          190 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1586            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1587              :         "The parameter, 'option' is not a ml-option handle.");
    1588              : 
    1589          189 :   _ml_info_destroy (option);
    1590              : 
    1591          189 :   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          320 : ml_option_set (ml_option_h option, const char *key, void *value,
    1606              :     ml_data_destroy_cb destroy)
    1607              : {
    1608          320 :   check_feature_state (ML_FEATURE);
    1609              : 
    1610          320 :   if (!option) {
    1611            1 :     _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          319 :   if (!key) {
    1616            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1617              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1618              :   }
    1619              : 
    1620          318 :   if (!value) {
    1621            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1622              :         "The parameter, 'value' is NULL. It should be a valid void*");
    1623              :   }
    1624              : 
    1625          317 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1626            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1627              :         "The parameter, 'option' is not a ml-option handle.");
    1628              : 
    1629          316 :   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          738 : ml_option_get (ml_option_h option, const char *key, void **value)
    1637              : {
    1638          738 :   check_feature_state (ML_FEATURE);
    1639              : 
    1640          738 :   if (!option) {
    1641            1 :     _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          737 :   if (!key) {
    1646            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1647              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1648              :   }
    1649              : 
    1650          736 :   if (!value) {
    1651            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1652              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1653              :   }
    1654              : 
    1655          735 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1656            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1657              :         "The parameter, 'option' is not a ml-option handle.");
    1658              : 
    1659          734 :   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           57 : _ml_information_create (ml_information_h * info)
    1667              : {
    1668           57 :   ml_info_s *_info = NULL;
    1669              : 
    1670           57 :   check_feature_state (ML_FEATURE);
    1671              : 
    1672           57 :   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           57 :   _info = _ml_info_create (ML_INFO_TYPE_INFORMATION);
    1678           57 :   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           57 :   *info = _info;
    1683           57 :   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          100 : _ml_information_set (ml_information_h information, const char *key, void *value,
    1692              :     ml_data_destroy_cb destroy)
    1693              : {
    1694          100 :   check_feature_state (ML_FEATURE);
    1695              : 
    1696          100 :   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          100 :   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          100 :   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          100 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1712            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1713              :         "The parameter, 'information' is not a ml-information handle.");
    1714              : 
    1715           99 :   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            2 : _ml_information_iter_internal (gpointer key, gpointer value, gpointer user_data)
    1723              : {
    1724            2 :   ml_info_iter_data_s *iter = (ml_info_iter_data_s *) user_data;
    1725            2 :   ml_info_value_s *info_value = (ml_info_value_s *) value;
    1726              : 
    1727            2 :   iter->callback (key, info_value->value, iter->user_data);
    1728            2 : }
    1729              : 
    1730              : /**
    1731              :  * @brief Iterates the key and value of each pair in ml-information.
    1732              :  */
    1733              : int
    1734            3 : 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            3 :   check_feature_state (ML_FEATURE);
    1741              : 
    1742            3 :   if (!_ml_info_is_valid (ml_info, ML_INFO_TYPE_INFORMATION)) {
    1743            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1744              :         "The parameter, 'ml_info' is not a ml-information handle.");
    1745              :   }
    1746              : 
    1747            2 :   if (!cb) {
    1748            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1749              :         "The parameter, 'cb' is NULL. It should be a valid function.");
    1750              :   }
    1751              : 
    1752            1 :   _info = (ml_info_s *) ml_info;
    1753              : 
    1754            1 :   iter = g_new0 (ml_info_iter_data_s, 1);
    1755            1 :   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            1 :   iter->callback = cb;
    1761            1 :   iter->user_data = user_data;
    1762              : 
    1763            1 :   g_hash_table_foreach (_info->table, _ml_information_iter_internal, iter);
    1764            1 :   g_free (iter);
    1765              : 
    1766            1 :   return ML_ERROR_NONE;
    1767              : }
    1768              : 
    1769              : /**
    1770              :  * @brief Frees the given handle of a ml_information.
    1771              :  */
    1772              : int
    1773           53 : ml_information_destroy (ml_information_h information)
    1774              : {
    1775           53 :   check_feature_state (ML_FEATURE);
    1776              : 
    1777           53 :   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           53 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1783            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1784              :         "The parameter, 'information' is not a ml-information handle.");
    1785              : 
    1786           52 :   _ml_info_destroy (information);
    1787              : 
    1788           52 :   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           71 : ml_information_get (ml_information_h information, const char *key, void **value)
    1796              : {
    1797           71 :   check_feature_state (ML_FEATURE);
    1798              : 
    1799           71 :   if (!information) {
    1800            1 :     _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           70 :   if (!key) {
    1805            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1806              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1807              :   }
    1808              : 
    1809           69 :   if (!value) {
    1810            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1811              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1812              :   }
    1813              : 
    1814           68 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1815            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1816              :         "The parameter, 'information' is not a ml-information handle.");
    1817              : 
    1818           67 :   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            5 : _ml_information_list_create (ml_information_list_h * list)
    1826              : {
    1827              :   ml_info_list_s *_info_list;
    1828              : 
    1829            5 :   check_feature_state (ML_FEATURE);
    1830              : 
    1831            5 :   if (!list)
    1832            1 :     _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            4 :   _info_list = g_try_new0 (ml_info_list_s, 1);
    1836            4 :   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            4 :   _info_list->type = ML_INFO_TYPE_INFORMATION_LIST;
    1842              : 
    1843            4 :   *list = _info_list;
    1844            4 :   return ML_ERROR_NONE;
    1845              : }
    1846              : 
    1847              : /**
    1848              :  * @brief Adds an ml-information into ml-information-list.
    1849              :  */
    1850              : int
    1851            7 : _ml_information_list_add (ml_information_list_h list, ml_information_h info)
    1852              : {
    1853              :   ml_info_list_s *_info_list;
    1854              : 
    1855            7 :   check_feature_state (ML_FEATURE);
    1856              : 
    1857            7 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1858            1 :     _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            6 :   if (!_ml_info_is_valid (info, ML_INFO_TYPE_OPTION) &&
    1863            6 :       !_ml_info_is_valid (info, ML_INFO_TYPE_INFORMATION)) {
    1864            1 :     _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            5 :   _info_list = (ml_info_list_s *) list;
    1869            5 :   _info_list->info = g_slist_append (_info_list->info, info);
    1870              : 
    1871            5 :   return ML_ERROR_NONE;
    1872              : }
    1873              : 
    1874              : /**
    1875              :  * @brief Destroys the ml-information-list instance.
    1876              :  */
    1877              : int
    1878            6 : ml_information_list_destroy (ml_information_list_h list)
    1879              : {
    1880              :   ml_info_list_s *_info_list;
    1881              : 
    1882            6 :   check_feature_state (ML_FEATURE);
    1883              : 
    1884            6 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1885            2 :     _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            4 :   _info_list = (ml_info_list_s *) list;
    1890            4 :   g_slist_free_full (_info_list->info, _ml_info_destroy);
    1891            4 :   g_free (_info_list);
    1892              : 
    1893            4 :   return ML_ERROR_NONE;
    1894              : }
    1895              : 
    1896              : /**
    1897              :  * @brief Gets the number of ml-information in ml-information-list instance.
    1898              :  */
    1899              : int
    1900            6 : ml_information_list_length (ml_information_list_h list, unsigned int *length)
    1901              : {
    1902              :   ml_info_list_s *_info_list;
    1903              : 
    1904            6 :   check_feature_state (ML_FEATURE);
    1905              : 
    1906            6 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1907            2 :     _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            4 :   if (!length) {
    1912            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1913              :         "The parameter, 'length' is NULL. It should be a valid unsigned int*");
    1914              :   }
    1915              : 
    1916            3 :   _info_list = (ml_info_list_s *) list;
    1917            3 :   *length = g_slist_length (_info_list->info);
    1918              : 
    1919            3 :   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            9 : 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            9 :   check_feature_state (ML_FEATURE);
    1932              : 
    1933            9 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1934            2 :     _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            7 :   if (!information) {
    1939            1 :     _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            6 :   _info_list = (ml_info_list_s *) list;
    1944            6 :   *information = g_slist_nth_data (_info_list->info, index);
    1945              : 
    1946            6 :   if (*information == NULL) {
    1947            1 :     _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            5 :   return ML_ERROR_NONE;
    1952              : }
        

Generated by: LCOV version 2.0-1