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#7f8530c294f86ec880b29347a861499239d358a1 Lines: 88.2 % 726 640
Test Date: 2025-06-06 05:24:38 Functions: 96.5 % 57 55

            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        19737 : _ml_tensors_info_create_internal (ml_tensors_info_h * info, bool extended)
     126              : {
     127              :   ml_tensors_info_s *tensors_info;
     128              : 
     129        19737 :   check_feature_state (ML_FEATURE);
     130              : 
     131        19737 :   if (!info)
     132            2 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     133              :         "The parameter, info, is NULL. Provide a valid pointer.");
     134              : 
     135        19735 :   *info = tensors_info = g_new0 (ml_tensors_info_s, 1);
     136        19735 :   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        19735 :   g_mutex_init (&tensors_info->lock);
     141        19735 :   tensors_info->is_extended = extended;
     142              : 
     143              :   /* init tensors info struct */
     144        19735 :   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         6682 : _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         6682 :   if (!in || !out)
     158            0 :     return ML_ERROR_INVALID_PARAMETER;
     159              : 
     160         6682 :   _info = (ml_tensors_info_s *) in;
     161              : 
     162         6682 :   if (_info->is_extended)
     163            7 :     status = ml_tensors_info_create_extended (out);
     164              :   else
     165         6675 :     status = ml_tensors_info_create (out);
     166              : 
     167         6682 :   if (status == ML_ERROR_NONE)
     168         6682 :     status = ml_tensors_info_clone (*out, in);
     169              : 
     170         6682 :   return status;
     171              : }
     172              : 
     173              : /**
     174              :  * @brief Allocates a tensors information handle with default value.
     175              :  */
     176              : int
     177        19702 : ml_tensors_info_create (ml_tensors_info_h * info)
     178              : {
     179        19702 :   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        19709 : ml_tensors_info_destroy (ml_tensors_info_h info)
     196              : {
     197              :   ml_tensors_info_s *tensors_info;
     198              : 
     199        19709 :   check_feature_state (ML_FEATURE);
     200              : 
     201        19709 :   tensors_info = (ml_tensors_info_s *) info;
     202              : 
     203        19709 :   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        19708 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     208        19708 :   _ml_tensors_info_free (tensors_info);
     209        19708 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     210              : 
     211        19708 :   g_mutex_clear (&tensors_info->lock);
     212        19708 :   g_free (tensors_info);
     213              : 
     214        19708 :   return ML_ERROR_NONE;
     215              : }
     216              : 
     217              : /**
     218              :  * @brief Validates the given tensors info is valid.
     219              :  */
     220              : int
     221         6514 : ml_tensors_info_validate (const ml_tensors_info_h info, bool *valid)
     222              : {
     223              :   ml_tensors_info_s *tensors_info;
     224              : 
     225         6514 :   check_feature_state (ML_FEATURE);
     226              : 
     227         6514 :   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         6513 :   tensors_info = (ml_tensors_info_s *) info;
     232              : 
     233         6513 :   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         6510 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     238         6510 :   *valid = gst_tensors_info_validate (&tensors_info->info);
     239         6510 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     240              : 
     241         6510 :   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        19736 : _ml_tensors_info_initialize (ml_tensors_info_s * info)
     653              : {
     654        19736 :   if (!info)
     655            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     656              :         "The parameter, info, is NULL. Provide a valid pointer.");
     657              : 
     658        19735 :   gst_tensors_info_init (&info->info);
     659              : 
     660        19735 :   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        19748 : _ml_tensors_info_free (ml_tensors_info_s * info)
     669              : {
     670        19748 :   if (!info)
     671            0 :     return;
     672              : 
     673        19748 :   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        12935 : _ml_tensors_data_destroy_internal (ml_tensors_data_h data, gboolean free_data)
     684              : {
     685        12935 :   int status = ML_ERROR_NONE;
     686              :   ml_tensors_data_s *_data;
     687              :   guint i;
     688              : 
     689        12935 :   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        12916 :   _data = (ml_tensors_data_s *) data;
     694        12916 :   G_LOCK_UNLESS_NOLOCK (*_data);
     695              : 
     696        12916 :   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        12916 :   if (_data->info)
     716        12916 :     ml_tensors_info_destroy (_data->info);
     717              : 
     718        12916 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     719        12916 :   g_mutex_clear (&_data->lock);
     720        12916 :   g_free (_data);
     721        12916 :   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        12939 : _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        12939 :   int status = ML_ERROR_NONE;
     752              : 
     753        12939 :   check_feature_state (ML_FEATURE);
     754              : 
     755        12939 :   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        12938 :   *data = NULL;
     761              : 
     762        12938 :   _data = g_new0 (ml_tensors_data_s, 1);
     763        12938 :   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        12938 :   g_mutex_init (&_data->lock);
     768              : 
     769        12938 :   _info = (ml_tensors_info_s *) info;
     770        12938 :   if (_info != NULL) {
     771         6673 :     status = _ml_tensors_info_create_from (info, &_data->info);
     772         6673 :     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         6673 :     G_LOCK_UNLESS_NOLOCK (*_info);
     779         6673 :     _data->num_tensors = _info->info.num_tensors;
     780        13786 :     for (i = 0; i < _data->num_tensors; i++) {
     781         7113 :       _data->tensors[i].size = gst_tensors_info_get_size (&_info->info, i);
     782         7113 :       _data->tensors[i].data = NULL;
     783              :     }
     784         6673 :     G_UNLOCK_UNLESS_NOLOCK (*_info);
     785              :   }
     786              : 
     787         6265 : error:
     788        12938 :   if (status == ML_ERROR_NONE) {
     789        12938 :     *data = _data;
     790              :   } else {
     791            0 :     _ml_tensors_data_destroy_internal (_data, FALSE);
     792              :   }
     793              : 
     794        12938 :   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 Copies the tensor data frame.
     837              :  */
     838              : int
     839          156 : ml_tensors_data_clone (const ml_tensors_data_h in, ml_tensors_data_h * out)
     840              : {
     841              :   int status;
     842              :   unsigned int i;
     843              :   ml_tensors_data_s *_in, *_out;
     844              : 
     845          156 :   check_feature_state (ML_FEATURE);
     846              : 
     847          156 :   if (in == NULL)
     848            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     849              :         "The parameter, in, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     850              : 
     851          155 :   if (out == NULL)
     852            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     853              :         "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);.");
     854              : 
     855          154 :   _in = (ml_tensors_data_s *) in;
     856          154 :   G_LOCK_UNLESS_NOLOCK (*_in);
     857              : 
     858          154 :   status = ml_tensors_data_create (_in->info, out);
     859          154 :   if (status != ML_ERROR_NONE) {
     860            0 :     _ml_loge ("Failed to create new handle to copy tensor data.");
     861            0 :     goto error;
     862              :   }
     863              : 
     864          154 :   _out = (ml_tensors_data_s *) (*out);
     865              : 
     866          464 :   for (i = 0; i < _out->num_tensors; ++i) {
     867          310 :     memcpy (_out->tensors[i].data, _in->tensors[i].data, _in->tensors[i].size);
     868              :   }
     869              : 
     870          154 : error:
     871          154 :   G_UNLOCK_UNLESS_NOLOCK (*_in);
     872          154 :   return status;
     873              : }
     874              : 
     875              : /**
     876              :  * @brief Gets the tensors information of given tensor data frame.
     877              :  */
     878              : int
     879            3 : ml_tensors_data_get_info (const ml_tensors_data_h data,
     880              :     ml_tensors_info_h * info)
     881              : {
     882              :   int status;
     883              :   ml_tensors_data_s *_data;
     884              : 
     885            3 :   check_feature_state (ML_FEATURE);
     886              : 
     887            3 :   if (data == NULL) {
     888            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     889              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     890              :   }
     891              : 
     892            2 :   if (info == NULL) {
     893            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     894              :         "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);.");
     895              :   }
     896              : 
     897            1 :   _data = (ml_tensors_data_s *) data;
     898            1 :   G_LOCK_UNLESS_NOLOCK (*_data);
     899              : 
     900            1 :   status = _ml_tensors_info_create_from (_data->info, info);
     901            1 :   if (status != ML_ERROR_NONE) {
     902            0 :     _ml_error_report_continue
     903              :         ("Failed to get the tensor information from data handle.");
     904              :   }
     905              : 
     906            1 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     907            1 :   return status;
     908              : }
     909              : 
     910              : /**
     911              :  * @brief Allocates a tensor data frame with the given tensors info. (more info in nnstreamer.h)
     912              :  */
     913              : int
     914         6420 : ml_tensors_data_create (const ml_tensors_info_h info, ml_tensors_data_h * data)
     915              : {
     916         6420 :   gint status = ML_ERROR_STREAMS_PIPE;
     917         6420 :   ml_tensors_data_s *_data = NULL;
     918              :   guint i;
     919              :   bool valid;
     920              : 
     921        12840 :   check_feature_state (ML_FEATURE);
     922              : 
     923         6420 :   if (info == NULL)
     924            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     925              :         "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().");
     926         6419 :   if (data == NULL)
     927            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     928              :         "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);.");
     929              : 
     930         6418 :   status = ml_tensors_info_validate (info, &valid);
     931         6418 :   if (status != ML_ERROR_NONE)
     932            0 :     _ml_error_report_return_continue (status,
     933              :         "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.");
     934         6418 :   if (!valid)
     935            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     936              :         "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.");
     937              : 
     938              :   status =
     939         6417 :       _ml_tensors_data_create_no_alloc (info, (ml_tensors_data_h *) & _data);
     940              : 
     941         6417 :   if (status != ML_ERROR_NONE) {
     942            0 :     _ml_error_report_return_continue (status,
     943              :         "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.",
     944              :         status);
     945              :   }
     946              : 
     947        13056 :   for (i = 0; i < _data->num_tensors; i++) {
     948         6639 :     _data->tensors[i].data = g_malloc0 (_data->tensors[i].size);
     949         6639 :     if (_data->tensors[i].data == NULL) {
     950            0 :       goto failed_oom;
     951              :     }
     952              :   }
     953              : 
     954         6417 :   *data = _data;
     955         6417 :   return ML_ERROR_NONE;
     956              : 
     957            0 : failed_oom:
     958            0 :   _ml_tensors_data_destroy_internal (_data, TRUE);
     959              : 
     960            0 :   _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
     961              :       "Failed to allocate memory blocks for tensors data. Check if it's out-of-memory.");
     962              : }
     963              : 
     964              : /**
     965              :  * @brief Gets a tensor data of given handle.
     966              :  */
     967              : int
     968          770 : ml_tensors_data_get_tensor_data (ml_tensors_data_h data, unsigned int index,
     969              :     void **raw_data, size_t *data_size)
     970              : {
     971              :   ml_tensors_data_s *_data;
     972          770 :   int status = ML_ERROR_NONE;
     973              : 
     974          770 :   check_feature_state (ML_FEATURE);
     975              : 
     976          770 :   if (data == NULL)
     977            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     978              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
     979          769 :   if (raw_data == NULL)
     980            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     981              :         "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.");
     982          768 :   if (data_size == NULL)
     983            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     984              :         "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.");
     985              : 
     986          767 :   _data = (ml_tensors_data_s *) data;
     987          767 :   G_LOCK_UNLESS_NOLOCK (*_data);
     988              : 
     989          767 :   if (_data->num_tensors <= index) {
     990            2 :     _ml_error_report
     991              :         ("The parameter, index, is out of bound. The number of tensors of 'data' is %u while you requested %u'th tensor (index = %u).",
     992              :         _data->num_tensors, index, index);
     993            2 :     status = ML_ERROR_INVALID_PARAMETER;
     994            2 :     goto report;
     995              :   }
     996              : 
     997          765 :   *raw_data = _data->tensors[index].data;
     998          765 :   *data_size = _data->tensors[index].size;
     999              : 
    1000          767 : report:
    1001          767 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1002          767 :   return status;
    1003              : }
    1004              : 
    1005              : /**
    1006              :  * @brief Copies a tensor data to given handle.
    1007              :  */
    1008              : int
    1009          281 : ml_tensors_data_set_tensor_data (ml_tensors_data_h data, unsigned int index,
    1010              :     const void *raw_data, const size_t data_size)
    1011              : {
    1012              :   ml_tensors_data_s *_data;
    1013          281 :   int status = ML_ERROR_NONE;
    1014              : 
    1015          281 :   check_feature_state (ML_FEATURE);
    1016              : 
    1017          281 :   if (data == NULL)
    1018            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1019              :         "The parameter, data, is NULL. It should be a valid ml_tensors_data_h handle, which is usually created by ml_tensors_data_create ().");
    1020          280 :   if (raw_data == NULL)
    1021            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1022              :         "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].",
    1023              :         index);
    1024              : 
    1025          279 :   _data = (ml_tensors_data_s *) data;
    1026          279 :   G_LOCK_UNLESS_NOLOCK (*_data);
    1027              : 
    1028          279 :   if (_data->num_tensors <= index) {
    1029            1 :     _ml_error_report
    1030              :         ("The parameter, index, is out of bound. The number of tensors of 'data' is %u, while you've requested index of %u.",
    1031              :         _data->num_tensors, index);
    1032            1 :     status = ML_ERROR_INVALID_PARAMETER;
    1033            1 :     goto report;
    1034              :   }
    1035              : 
    1036          278 :   if (data_size <= 0 || _data->tensors[index].size < data_size) {
    1037            2 :     _ml_error_report
    1038              :         ("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).",
    1039              :         data_size, index, _data->tensors[index].size);
    1040            2 :     status = ML_ERROR_INVALID_PARAMETER;
    1041            2 :     goto report;
    1042              :   }
    1043              : 
    1044          276 :   if (_data->tensors[index].data != raw_data)
    1045          273 :     memcpy (_data->tensors[index].data, raw_data, data_size);
    1046              : 
    1047            3 : report:
    1048          279 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1049          279 :   return status;
    1050              : }
    1051              : 
    1052              : /**
    1053              :  * @brief Copies tensor meta info.
    1054              :  */
    1055              : int
    1056         6695 : ml_tensors_info_clone (ml_tensors_info_h dest, const ml_tensors_info_h src)
    1057              : {
    1058              :   ml_tensors_info_s *dest_info, *src_info;
    1059         6695 :   int status = ML_ERROR_NONE;
    1060              : 
    1061         6695 :   check_feature_state (ML_FEATURE);
    1062              : 
    1063         6695 :   dest_info = (ml_tensors_info_s *) dest;
    1064         6695 :   src_info = (ml_tensors_info_s *) src;
    1065              : 
    1066         6695 :   if (!dest_info)
    1067            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1068              :         "The parameter, dest, is NULL. It should be an allocated handle (ml_tensors_info_h), usually allocated by ml_tensors_info_create ().");
    1069         6694 :   if (!src_info)
    1070            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1071              :         "The parameter, src, is NULL. It should be a handle (ml_tensors_info_h) with valid data.");
    1072              : 
    1073         6693 :   G_LOCK_UNLESS_NOLOCK (*dest_info);
    1074         6693 :   G_LOCK_UNLESS_NOLOCK (*src_info);
    1075              : 
    1076         6693 :   if (gst_tensors_info_validate (&src_info->info)) {
    1077         6693 :     dest_info->is_extended = src_info->is_extended;
    1078         6693 :     gst_tensors_info_copy (&dest_info->info, &src_info->info);
    1079              :   } else {
    1080            0 :     _ml_error_report
    1081              :         ("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.",
    1082              :         ML_TENSOR_SIZE_LIMIT);
    1083            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1084              :   }
    1085              : 
    1086         6693 :   G_UNLOCK_UNLESS_NOLOCK (*src_info);
    1087         6693 :   G_UNLOCK_UNLESS_NOLOCK (*dest_info);
    1088              : 
    1089         6693 :   return status;
    1090              : }
    1091              : 
    1092              : /**
    1093              :  * @brief Replaces string.
    1094              :  * This function deallocates the input source string.
    1095              :  * This is copied from nnstreamer/tensor_common.c by the nnstreamer maintainer.
    1096              :  * @param[in] source The input string. This will be freed when returning the replaced string.
    1097              :  * @param[in] what The string to search for.
    1098              :  * @param[in] to The string to be replaced.
    1099              :  * @param[in] delimiters The characters which specify the place to split the string. Set NULL to replace all matched string.
    1100              :  * @param[out] count The count of replaced. Set NULL if it is unnecessary.
    1101              :  * @return Newly allocated string. The returned string should be freed with g_free().
    1102              :  */
    1103              : gchar *
    1104           15 : _ml_replace_string (gchar * source, const gchar * what, const gchar * to,
    1105              :     const gchar * delimiters, guint * count)
    1106              : {
    1107              :   GString *builder;
    1108              :   gchar *start, *pos, *result;
    1109           15 :   guint changed = 0;
    1110              :   gsize len;
    1111              : 
    1112           15 :   g_return_val_if_fail (source, NULL);
    1113           15 :   g_return_val_if_fail (what && to, source);
    1114              : 
    1115           15 :   len = strlen (what);
    1116           15 :   start = source;
    1117              : 
    1118           15 :   builder = g_string_new (NULL);
    1119           57 :   while ((pos = g_strstr_len (start, -1, what)) != NULL) {
    1120           42 :     gboolean skip = FALSE;
    1121              : 
    1122           42 :     if (delimiters) {
    1123              :       const gchar *s;
    1124              :       gchar *prev, *next;
    1125              :       gboolean prev_split, next_split;
    1126              : 
    1127           22 :       prev = next = NULL;
    1128           22 :       prev_split = next_split = FALSE;
    1129              : 
    1130           22 :       if (pos != source)
    1131           18 :         prev = pos - 1;
    1132           22 :       if (*(pos + len) != '\0')
    1133           19 :         next = pos + len;
    1134              : 
    1135           46 :       for (s = delimiters; *s != '\0'; ++s) {
    1136           34 :         if (!prev || *s == *prev)
    1137           16 :           prev_split = TRUE;
    1138           34 :         if (!next || *s == *next)
    1139           15 :           next_split = TRUE;
    1140           34 :         if (prev_split && next_split)
    1141           10 :           break;
    1142              :       }
    1143              : 
    1144           22 :       if (!prev_split || !next_split)
    1145           12 :         skip = TRUE;
    1146              :     }
    1147              : 
    1148           42 :     builder = g_string_append_len (builder, start, pos - start);
    1149              : 
    1150              :     /* replace string if found */
    1151           42 :     if (skip)
    1152           24 :       builder = g_string_append_len (builder, pos, len);
    1153              :     else
    1154           30 :       builder = g_string_append (builder, to);
    1155              : 
    1156           42 :     start = pos + len;
    1157           42 :     if (!skip)
    1158           30 :       changed++;
    1159              :   }
    1160              : 
    1161              :   /* append remains */
    1162           15 :   builder = g_string_append (builder, start);
    1163           15 :   result = g_string_free (builder, FALSE);
    1164              : 
    1165           15 :   if (count)
    1166            9 :     *count = changed;
    1167              : 
    1168           15 :   g_free (source);
    1169           15 :   return result;
    1170              : }
    1171              : 
    1172              : /**
    1173              :  * @brief Converts predefined entity.
    1174              :  */
    1175              : gchar *
    1176          343 : _ml_convert_predefined_entity (const gchar * str)
    1177              : {
    1178          343 :   gchar *converted = g_strdup (str);
    1179              : 
    1180              : #if defined(__ANDROID__)
    1181              :   {
    1182              :     extern const char *nnstreamer_native_get_data_path (void);
    1183              : 
    1184              :     const char *data_path = nnstreamer_native_get_data_path ();
    1185              : 
    1186              :     converted = _ml_replace_string (converted, "@APP_DATA_PATH@", data_path,
    1187              :         NULL, NULL);
    1188              :   }
    1189              : #endif
    1190              : 
    1191          343 :   return converted;
    1192              : }
    1193              : 
    1194              : /**
    1195              :  * @brief error reporting infra
    1196              :  */
    1197              : #define _ML_ERRORMSG_LENGTH (4096U)
    1198              : static char errormsg[_ML_ERRORMSG_LENGTH] = { 0 };      /* one page limit */
    1199              : 
    1200              : static int reported = 0;
    1201              : G_LOCK_DEFINE_STATIC (errlock);
    1202              : 
    1203              : /**
    1204              :  * @brief public API function of error reporting.
    1205              :  */
    1206              : const char *
    1207            0 : ml_error (void)
    1208              : {
    1209            0 :   G_LOCK (errlock);
    1210            0 :   if (reported != 0) {
    1211            0 :     errormsg[0] = '\0';
    1212            0 :     reported = 0;
    1213              :   }
    1214            0 :   if (errormsg[0] == '\0') {
    1215            0 :     G_UNLOCK (errlock);
    1216            0 :     return NULL;
    1217              :   }
    1218              : 
    1219            0 :   reported = 1;
    1220              : 
    1221            0 :   G_UNLOCK (errlock);
    1222            0 :   return errormsg;
    1223              : }
    1224              : 
    1225              : /**
    1226              :  * @brief Internal interface to write messages for ml_error()
    1227              :  */
    1228              : void
    1229          554 : _ml_error_report_ (const char *fmt, ...)
    1230              : {
    1231              :   int n;
    1232              :   va_list arg_ptr;
    1233          554 :   G_LOCK (errlock);
    1234              : 
    1235          554 :   va_start (arg_ptr, fmt);
    1236          554 :   n = vsnprintf (errormsg, _ML_ERRORMSG_LENGTH, fmt, arg_ptr);
    1237          554 :   va_end (arg_ptr);
    1238              : 
    1239          554 :   if (n > _ML_ERRORMSG_LENGTH) {
    1240            0 :     errormsg[_ML_ERRORMSG_LENGTH - 2] = '.';
    1241            0 :     errormsg[_ML_ERRORMSG_LENGTH - 3] = '.';
    1242            0 :     errormsg[_ML_ERRORMSG_LENGTH - 4] = '.';
    1243              :   }
    1244              : 
    1245          554 :   _ml_loge ("%s", errormsg);
    1246              : 
    1247          554 :   reported = 0;
    1248              : 
    1249          554 :   G_UNLOCK (errlock);
    1250          554 : }
    1251              : 
    1252              : /**
    1253              :  * @brief Internal interface to write messages for ml_error(), relaying previously reported errors.
    1254              :  */
    1255              : void
    1256           44 : _ml_error_report_continue_ (const char *fmt, ...)
    1257              : {
    1258           44 :   size_t cursor = 0;
    1259              :   va_list arg_ptr;
    1260              :   char buf[_ML_ERRORMSG_LENGTH];
    1261           44 :   G_LOCK (errlock);
    1262              : 
    1263              :   /* Check if there is a message to relay */
    1264           44 :   if (reported == 0) {
    1265           44 :     cursor = strlen (errormsg);
    1266           44 :     if (cursor < (_ML_ERRORMSG_LENGTH - 1)) {
    1267           44 :       errormsg[cursor] = '\n';
    1268           44 :       errormsg[cursor + 1] = '\0';
    1269           44 :       cursor++;
    1270              :     }
    1271              :   } else {
    1272            0 :     errormsg[0] = '\0';
    1273              :   }
    1274              : 
    1275           44 :   va_start (arg_ptr, fmt);
    1276           44 :   vsnprintf (buf, _ML_ERRORMSG_LENGTH - 1, fmt, arg_ptr);
    1277           44 :   _ml_loge ("%s", buf);
    1278              : 
    1279           44 :   memcpy (errormsg + cursor, buf, _ML_ERRORMSG_LENGTH - strlen (errormsg) - 1);
    1280           44 :   if (strlen (errormsg) >= (_ML_ERRORMSG_LENGTH - 2)) {
    1281            0 :     errormsg[_ML_ERRORMSG_LENGTH - 2] = '.';
    1282            0 :     errormsg[_ML_ERRORMSG_LENGTH - 3] = '.';
    1283            0 :     errormsg[_ML_ERRORMSG_LENGTH - 4] = '.';
    1284              :   }
    1285              : 
    1286           44 :   va_end (arg_ptr);
    1287              : 
    1288           44 :   errormsg[_ML_ERRORMSG_LENGTH - 1] = '\0';
    1289           44 :   reported = 0;
    1290           44 :   G_UNLOCK (errlock);
    1291           44 : }
    1292              : 
    1293              : static const char *strerrors[] = {
    1294              :   [0] = "Not an error",
    1295              :   [EINVAL] =
    1296              :       "Invalid parameters are given to a function. Check parameter values. (EINVAL)",
    1297              : };
    1298              : 
    1299              : /**
    1300              :  * @brief public API function of error code descriptions
    1301              :  */
    1302              : const char *
    1303            0 : ml_strerror (int errnum)
    1304              : {
    1305            0 :   int size = sizeof (strerrors) / sizeof (strerrors[0]);
    1306              : 
    1307            0 :   if (errnum < 0)
    1308            0 :     errnum = errnum * -1;
    1309              : 
    1310            0 :   if (errnum == 0 || errnum >= size)
    1311            0 :     return NULL;
    1312            0 :   return strerrors[errnum];
    1313              : }
    1314              : 
    1315              : /**
    1316              :  * @brief Internal function to check the handle is valid.
    1317              :  */
    1318              : static bool
    1319         1347 : _ml_info_is_valid (gpointer handle, ml_info_type_e expected)
    1320              : {
    1321              :   ml_info_type_e current;
    1322              : 
    1323         1347 :   if (!handle)
    1324            6 :     return false;
    1325              : 
    1326              :   /* The first field should be an enum value of ml_info_type_e. */
    1327         1341 :   current = *((ml_info_type_e *) handle);
    1328         1341 :   if (current != expected)
    1329           14 :     return false;
    1330              : 
    1331         1327 :   switch (current) {
    1332         1306 :     case ML_INFO_TYPE_OPTION:
    1333              :     case ML_INFO_TYPE_INFORMATION:
    1334              :     {
    1335         1306 :       ml_info_s *_info = (ml_info_s *) handle;
    1336              : 
    1337         1306 :       if (!_info->table)
    1338            0 :         return false;
    1339              : 
    1340         1306 :       break;
    1341              :     }
    1342           21 :     case ML_INFO_TYPE_INFORMATION_LIST:
    1343           21 :       break;
    1344            0 :     default:
    1345              :       /* Unknown type */
    1346            0 :       return false;
    1347              :   }
    1348              : 
    1349         1327 :   return true;
    1350              : }
    1351              : 
    1352              : /**
    1353              :  * @brief Internal function for destroy value of option table
    1354              :  */
    1355              : static void
    1356          408 : _ml_info_value_free (gpointer data)
    1357              : {
    1358              :   ml_info_value_s *_value;
    1359              : 
    1360          408 :   _value = (ml_info_value_s *) data;
    1361          408 :   if (_value) {
    1362          408 :     if (_value->destroy)
    1363          345 :       _value->destroy (_value->value);
    1364          408 :     g_free (_value);
    1365              :   }
    1366          408 : }
    1367              : 
    1368              : /**
    1369              :  * @brief Internal function for create ml_info
    1370              :  */
    1371              : static ml_info_s *
    1372          248 : _ml_info_create (ml_info_type_e type)
    1373              : {
    1374              :   ml_info_s *info;
    1375              : 
    1376          248 :   info = g_new0 (ml_info_s, 1);
    1377          248 :   if (info == NULL) {
    1378            0 :     _ml_error_report
    1379              :         ("Failed to allocate memory for the ml_info. Out of memory?");
    1380            0 :     return NULL;
    1381              :   }
    1382              : 
    1383          248 :   info->type = type;
    1384          248 :   info->table =
    1385          248 :       g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
    1386              :       _ml_info_value_free);
    1387          248 :   if (info->table == NULL) {
    1388            0 :     _ml_error_report
    1389              :         ("Failed to allocate memory for the table of ml_info. Out of memory?");
    1390            0 :     g_free (info);
    1391            0 :     return NULL;
    1392              :   }
    1393              : 
    1394          248 :   return info;
    1395              : }
    1396              : 
    1397              : /**
    1398              :  * @brief Internal function for destroy ml_info
    1399              :  */
    1400              : static void
    1401          244 : _ml_info_destroy (gpointer data)
    1402              : {
    1403          244 :   ml_info_s *info = (ml_info_s *) data;
    1404              : 
    1405          244 :   if (!info)
    1406            0 :     return;
    1407              : 
    1408          244 :   info->type = ML_INFO_TYPE_UNKNOWN;
    1409              : 
    1410          244 :   if (info->table) {
    1411          244 :     g_hash_table_destroy (info->table);
    1412          244 :     info->table = NULL;
    1413              :   }
    1414              : 
    1415          244 :   g_free (info);
    1416          244 :   return;
    1417              : }
    1418              : 
    1419              : /**
    1420              :  * @brief Internal function for set value of given ml_info
    1421              :  */
    1422              : static int
    1423          413 : _ml_info_set_value (ml_info_s * info, const char *key, void *value,
    1424              :     ml_data_destroy_cb destroy)
    1425              : {
    1426              :   ml_info_value_s *info_value;
    1427              : 
    1428          413 :   if (!STR_IS_VALID (key))
    1429            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1430              :         "The parameter, 'key' is invalid. It should be a valid string.");
    1431              : 
    1432          412 :   if (!info || !value)
    1433            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1434              :         "The parameter, 'info' or 'value' is NULL. It should be a valid ml_info and value.");
    1435              : 
    1436          412 :   info_value = g_new0 (ml_info_value_s, 1);
    1437          412 :   if (!info_value)
    1438            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1439              :         "Failed to allocate memory for the info value. Out of memory?");
    1440              : 
    1441          412 :   info_value->value = value;
    1442          412 :   info_value->destroy = destroy;
    1443          412 :   g_hash_table_insert (info->table, g_strdup (key), (gpointer) info_value);
    1444              : 
    1445          412 :   return ML_ERROR_NONE;
    1446              : }
    1447              : 
    1448              : /**
    1449              :  * @brief Internal function for get value of given ml_info
    1450              :  */
    1451              : static int
    1452          649 : _ml_info_get_value (ml_info_s * info, const char *key, void **value)
    1453              : {
    1454              :   ml_info_value_s *info_value;
    1455              : 
    1456          649 :   if (!info || !key || !value)
    1457            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1458              :         "The parameter, 'info', 'key' or 'value' is NULL. It should be a valid ml_info, key and value.");
    1459              : 
    1460          649 :   info_value = g_hash_table_lookup (info->table, key);
    1461          649 :   if (!info_value)
    1462          310 :     return ML_ERROR_INVALID_PARAMETER;
    1463              : 
    1464          339 :   *value = info_value->value;
    1465              : 
    1466          339 :   return ML_ERROR_NONE;
    1467              : }
    1468              : 
    1469              : /**
    1470              :  * @brief Creates an option and returns the instance a handle.
    1471              :  */
    1472              : int
    1473          194 : ml_option_create (ml_option_h * option)
    1474              : {
    1475          194 :   ml_info_s *_option = NULL;
    1476              : 
    1477          194 :   check_feature_state (ML_FEATURE);
    1478              : 
    1479          194 :   if (!option) {
    1480            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1481              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h");
    1482              :   }
    1483              : 
    1484          193 :   _option = _ml_info_create (ML_INFO_TYPE_OPTION);
    1485          193 :   if (_option == NULL)
    1486            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1487              :         "Failed to allocate memory for the option handle. Out of memory?");
    1488              : 
    1489          193 :   *option = _option;
    1490          193 :   return ML_ERROR_NONE;
    1491              : }
    1492              : 
    1493              : /**
    1494              :  * @brief Frees the given handle of a ml_option.
    1495              :  */
    1496              : int
    1497          191 : ml_option_destroy (ml_option_h option)
    1498              : {
    1499          191 :   check_feature_state (ML_FEATURE);
    1500              : 
    1501          191 :   if (!option) {
    1502            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1503              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1504              :   }
    1505              : 
    1506          190 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1507            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1508              :         "The parameter, 'option' is not a ml-option handle.");
    1509              : 
    1510          189 :   _ml_info_destroy (option);
    1511              : 
    1512          189 :   return ML_ERROR_NONE;
    1513              : }
    1514              : 
    1515              : /**
    1516              :  * @brief Set key-value pair in given option handle. Note that if duplicated key is given, the value is updated with the new one.
    1517              :  * If some options are changed or there are newly added options, please modify below description.
    1518              :  * The list of valid key-values are:
    1519              :  *
    1520              :  * key (char *)     || value (expected type (pointer))
    1521              :  * ---------------------------------------------------------
    1522              :  * "framework_name" ||  explicit name of framework (char *)
    1523              :  * ...
    1524              :  */
    1525              : int
    1526          320 : ml_option_set (ml_option_h option, const char *key, void *value,
    1527              :     ml_data_destroy_cb destroy)
    1528              : {
    1529          320 :   check_feature_state (ML_FEATURE);
    1530              : 
    1531          320 :   if (!option) {
    1532            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1533              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1534              :   }
    1535              : 
    1536          319 :   if (!key) {
    1537            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1538              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1539              :   }
    1540              : 
    1541          318 :   if (!value) {
    1542            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1543              :         "The parameter, 'value' is NULL. It should be a valid void*");
    1544              :   }
    1545              : 
    1546          317 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1547            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1548              :         "The parameter, 'option' is not a ml-option handle.");
    1549              : 
    1550          316 :   return _ml_info_set_value ((ml_info_s *) option, key, value, destroy);
    1551              : }
    1552              : 
    1553              : /**
    1554              :  * @brief Gets a value of key in ml_option instance.
    1555              :  */
    1556              : int
    1557          586 : ml_option_get (ml_option_h option, const char *key, void **value)
    1558              : {
    1559          586 :   check_feature_state (ML_FEATURE);
    1560              : 
    1561          586 :   if (!option) {
    1562            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1563              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1564              :   }
    1565              : 
    1566          585 :   if (!key) {
    1567            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1568              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1569              :   }
    1570              : 
    1571          584 :   if (!value) {
    1572            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1573              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1574              :   }
    1575              : 
    1576          583 :   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          582 :   return _ml_info_get_value ((ml_info_s *) option, key, value);
    1581              : }
    1582              : 
    1583              : /**
    1584              :  * @brief Creates an ml_information instance and returns the handle.
    1585              :  */
    1586              : int
    1587           55 : _ml_information_create (ml_information_h * info)
    1588              : {
    1589           55 :   ml_info_s *_info = NULL;
    1590              : 
    1591           55 :   check_feature_state (ML_FEATURE);
    1592              : 
    1593           55 :   if (!info) {
    1594            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1595              :         "The parameter, 'info' is NULL. It should be a valid ml_information_h");
    1596              :   }
    1597              : 
    1598           55 :   _info = _ml_info_create (ML_INFO_TYPE_INFORMATION);
    1599           55 :   if (!_info)
    1600            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1601              :         "Failed to allocate memory for the info handle. Out of memory?");
    1602              : 
    1603           55 :   *info = _info;
    1604           55 :   return ML_ERROR_NONE;
    1605              : }
    1606              : 
    1607              : /**
    1608              :  * @brief Set key-value pair in given information handle.
    1609              :  * @note If duplicated key is given, the value is updated with the new one.
    1610              :  */
    1611              : int
    1612           98 : _ml_information_set (ml_information_h information, const char *key, void *value,
    1613              :     ml_data_destroy_cb destroy)
    1614              : {
    1615           98 :   check_feature_state (ML_FEATURE);
    1616              : 
    1617           98 :   if (!information) {
    1618            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1619              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1620              :   }
    1621              : 
    1622           98 :   if (!key) {
    1623            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1624              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1625              :   }
    1626              : 
    1627           98 :   if (!value) {
    1628            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1629              :         "The parameter, 'value' is NULL. It should be a valid void*");
    1630              :   }
    1631              : 
    1632           98 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1633            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1634              :         "The parameter, 'information' is not a ml-information handle.");
    1635              : 
    1636           97 :   return _ml_info_set_value ((ml_info_s *) information, key, value, destroy);
    1637              : }
    1638              : 
    1639              : /**
    1640              :  * @brief Frees the given handle of a ml_information.
    1641              :  */
    1642              : int
    1643           51 : ml_information_destroy (ml_information_h information)
    1644              : {
    1645           51 :   check_feature_state (ML_FEATURE);
    1646              : 
    1647           51 :   if (!information) {
    1648            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1649              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1650              :   }
    1651              : 
    1652           51 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1653            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1654              :         "The parameter, 'information' is not a ml-information handle.");
    1655              : 
    1656           50 :   _ml_info_destroy (information);
    1657              : 
    1658           50 :   return ML_ERROR_NONE;
    1659              : }
    1660              : 
    1661              : /**
    1662              :  * @brief Gets the value corresponding to the given key in ml_information instance.
    1663              :  */
    1664              : int
    1665           71 : ml_information_get (ml_information_h information, const char *key, void **value)
    1666              : {
    1667           71 :   check_feature_state (ML_FEATURE);
    1668              : 
    1669           71 :   if (!information) {
    1670            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1671              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1672              :   }
    1673              : 
    1674           70 :   if (!key) {
    1675            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1676              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1677              :   }
    1678              : 
    1679           69 :   if (!value) {
    1680            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1681              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1682              :   }
    1683              : 
    1684           68 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1685            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1686              :         "The parameter, 'information' is not a ml-information handle.");
    1687              : 
    1688           67 :   return _ml_info_get_value ((ml_info_s *) information, key, value);
    1689              : }
    1690              : 
    1691              : /**
    1692              :  * @brief Creates an ml-information-list instance and returns the handle.
    1693              :  */
    1694              : int
    1695            5 : _ml_information_list_create (ml_information_list_h * list)
    1696              : {
    1697              :   ml_info_list_s *_info_list;
    1698              : 
    1699            5 :   check_feature_state (ML_FEATURE);
    1700              : 
    1701            5 :   if (!list)
    1702            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1703              :         "The parameter, 'list' is NULL. It should be a valid ml_information_list_h.");
    1704              : 
    1705            4 :   _info_list = g_try_new0 (ml_info_list_s, 1);
    1706            4 :   if (!_info_list) {
    1707            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1708              :         "Failed to allocate memory for ml_information_list_h. Out of memory?");
    1709              :   }
    1710              : 
    1711            4 :   _info_list->type = ML_INFO_TYPE_INFORMATION_LIST;
    1712              : 
    1713            4 :   *list = _info_list;
    1714            4 :   return ML_ERROR_NONE;
    1715              : }
    1716              : 
    1717              : /**
    1718              :  * @brief Adds an ml-information into ml-information-list.
    1719              :  */
    1720              : int
    1721            7 : _ml_information_list_add (ml_information_list_h list, ml_information_h info)
    1722              : {
    1723              :   ml_info_list_s *_info_list;
    1724              : 
    1725            7 :   check_feature_state (ML_FEATURE);
    1726              : 
    1727            7 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1728            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1729              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1730              :   }
    1731              : 
    1732            6 :   if (!_ml_info_is_valid (info, ML_INFO_TYPE_OPTION) &&
    1733            6 :       !_ml_info_is_valid (info, ML_INFO_TYPE_INFORMATION)) {
    1734            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1735              :         "The parameter, 'info' is invalid. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1736              :   }
    1737              : 
    1738            5 :   _info_list = (ml_info_list_s *) list;
    1739            5 :   _info_list->info = g_slist_append (_info_list->info, info);
    1740              : 
    1741            5 :   return ML_ERROR_NONE;
    1742              : }
    1743              : 
    1744              : /**
    1745              :  * @brief Destroys the ml-information-list instance.
    1746              :  */
    1747              : int
    1748            6 : ml_information_list_destroy (ml_information_list_h list)
    1749              : {
    1750              :   ml_info_list_s *_info_list;
    1751              : 
    1752            6 :   check_feature_state (ML_FEATURE);
    1753              : 
    1754            6 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1755            2 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1756              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1757              :   }
    1758              : 
    1759            4 :   _info_list = (ml_info_list_s *) list;
    1760            4 :   g_slist_free_full (_info_list->info, _ml_info_destroy);
    1761            4 :   g_free (_info_list);
    1762              : 
    1763            4 :   return ML_ERROR_NONE;
    1764              : }
    1765              : 
    1766              : /**
    1767              :  * @brief Gets the number of ml-information in ml-information-list instance.
    1768              :  */
    1769              : int
    1770            6 : ml_information_list_length (ml_information_list_h list, unsigned int *length)
    1771              : {
    1772              :   ml_info_list_s *_info_list;
    1773              : 
    1774            6 :   check_feature_state (ML_FEATURE);
    1775              : 
    1776            6 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1777            2 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1778              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1779              :   }
    1780              : 
    1781            4 :   if (!length) {
    1782            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1783              :         "The parameter, 'length' is NULL. It should be a valid unsigned int*");
    1784              :   }
    1785              : 
    1786            3 :   _info_list = (ml_info_list_s *) list;
    1787            3 :   *length = g_slist_length (_info_list->info);
    1788              : 
    1789            3 :   return ML_ERROR_NONE;
    1790              : }
    1791              : 
    1792              : /**
    1793              :  * @brief Gets a ml-information in ml-information-list instance with given index.
    1794              :  */
    1795              : int
    1796            9 : ml_information_list_get (ml_information_list_h list, unsigned int index,
    1797              :     ml_information_h * information)
    1798              : {
    1799              :   ml_info_list_s *_info_list;
    1800              : 
    1801            9 :   check_feature_state (ML_FEATURE);
    1802              : 
    1803            9 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1804            2 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1805              :         "The parameter, 'list' is NULL. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1806              :   }
    1807              : 
    1808            7 :   if (!information) {
    1809            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1810              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h*");
    1811              :   }
    1812              : 
    1813            6 :   _info_list = (ml_info_list_s *) list;
    1814            6 :   *information = g_slist_nth_data (_info_list->info, index);
    1815              : 
    1816            6 :   if (*information == NULL) {
    1817            1 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1818              :         "The parameter, 'index' is invalid. It should be less than the length of ml_information_list_h.");
    1819              :   }
    1820              : 
    1821            5 :   return ML_ERROR_NONE;
    1822              : }
        

Generated by: LCOV version 2.0-1