LCOV - code coverage report
Current view: top level - capi-machine-learning-inference-1.8.6/c/src - ml-api-common.c (source / functions) Coverage Total Hit
Test: ML API 1.8.6-0 nnstreamer/api#abde31caf90ada0ea14929b563b6d19f563740eb Lines: 86.9 % 756 657
Test Date: 2025-08-15 05:27:32 Functions: 96.6 % 58 56

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

Generated by: LCOV version 2.0-1