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

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

Generated by: LCOV version 2.4-0