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 platform/core/api/machine-learning#681b884c6a50f3134065311d1610991dcdde916e Lines: 0.0 % 723 0
Test Date: 2024-10-30 18:02:44 Functions: 0.0 % 56 0

            Line data    Source code
       1              : /* SPDX-License-Identifier: Apache-2.0 */
       2              : /**
       3              :  * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved.
       4              :  *
       5              :  * @file nnstreamer-capi-util.c
       6              :  * @date 10 June 2019
       7              :  * @brief NNStreamer/Utilities C-API Wrapper.
       8              :  * @see https://github.com/nnstreamer/nnstreamer
       9              :  * @author MyungJoo Ham <myungjoo.ham@samsung.com>
      10              :  * @bug No known bugs except for NYI items
      11              :  */
      12              : 
      13              : #include <string.h>
      14              : #include <stdio.h>
      15              : #include <stdarg.h>
      16              : #include <glib.h>
      17              : #include <nnstreamer_plugin_api_util.h>
      18              : #include "nnstreamer.h"
      19              : #include "nnstreamer-tizen-internal.h"
      20              : #include "ml-api-internal.h"
      21              : 
      22              : /**
      23              :  * @brief Enumeration for ml_info type.
      24              :  */
      25              : typedef enum
      26              : {
      27              :   ML_INFO_TYPE_UNKNOWN = 0,
      28              :   ML_INFO_TYPE_OPTION = 0xfeed0001,
      29              :   ML_INFO_TYPE_INFORMATION = 0xfeed0010,
      30              :   ML_INFO_TYPE_INFORMATION_LIST = 0xfeed0011,
      31              : 
      32              :   ML_INFO_TYPE_MAX = 0xfeedffff
      33              : } ml_info_type_e;
      34              : 
      35              : /**
      36              :  * @brief Data structure for value of ml_info.
      37              :  */
      38              : typedef struct
      39              : {
      40              :   void *value; /**< The data given by user. */
      41              :   ml_data_destroy_cb destroy; /**< The destroy func given by user. */
      42              : } ml_info_value_s;
      43              : 
      44              : /**
      45              :  * @brief Data structure for ml_info.
      46              :  */
      47              : typedef struct
      48              : {
      49              :   ml_info_type_e type; /**< The type of ml_info. */
      50              :   GHashTable *table; /**< hash table used by ml_info. */
      51              : } ml_info_s;
      52              : 
      53              : /**
      54              :  * @brief Data structure for ml_info_list.
      55              :  */
      56              : typedef struct
      57              : {
      58              :   ml_info_type_e type; /**< The type of ml_info. */
      59              :   GSList *info; /**< The list of ml_info. */
      60              : } ml_info_list_s;
      61              : 
      62              : /**
      63              :  * @brief Gets the version number of machine-learning API.
      64              :  */
      65              : void
      66            0 : ml_api_get_version (unsigned int *major, unsigned int *minor,
      67              :     unsigned int *micro)
      68              : {
      69            0 :   if (major)
      70            0 :     *major = VERSION_MAJOR;
      71            0 :   if (minor)
      72            0 :     *minor = VERSION_MINOR;
      73            0 :   if (micro)
      74            0 :     *micro = VERSION_MICRO;
      75            0 : }
      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            0 : convert_tensor_type_from (ml_tensor_type_e type)
      84              : {
      85            0 :   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            0 :   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            0 : convert_ml_tensor_type_from (tensor_type type)
     102              : {
     103            0 :   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            0 :   return (ml_tensor_type_e) type;
     110              : }
     111              : 
     112              : /**
     113              :  * @brief Gets the version string of machine-learning API.
     114              :  */
     115              : char *
     116            0 : ml_api_get_version_string (void)
     117              : {
     118            0 :   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            0 : _ml_tensors_info_create_internal (ml_tensors_info_h * info, bool extended)
     126              : {
     127              :   ml_tensors_info_s *tensors_info;
     128              : 
     129            0 :   check_feature_state (ML_FEATURE);
     130              : 
     131            0 :   if (!info)
     132            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     133              :         "The parameter, info, is NULL. Provide a valid pointer.");
     134              : 
     135            0 :   *info = tensors_info = g_new0 (ml_tensors_info_s, 1);
     136            0 :   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            0 :   g_mutex_init (&tensors_info->lock);
     141            0 :   tensors_info->is_extended = extended;
     142              : 
     143              :   /* init tensors info struct */
     144            0 :   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            0 : _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            0 :   if (!in || !out)
     158            0 :     return ML_ERROR_INVALID_PARAMETER;
     159              : 
     160            0 :   _info = (ml_tensors_info_s *) in;
     161              : 
     162            0 :   if (_info->is_extended)
     163            0 :     status = ml_tensors_info_create_extended (out);
     164              :   else
     165            0 :     status = ml_tensors_info_create (out);
     166              : 
     167            0 :   if (status == ML_ERROR_NONE)
     168            0 :     status = ml_tensors_info_clone (*out, in);
     169              : 
     170            0 :   return status;
     171              : }
     172              : 
     173              : /**
     174              :  * @brief Allocates a tensors information handle with default value.
     175              :  */
     176              : int
     177            0 : ml_tensors_info_create (ml_tensors_info_h * info)
     178              : {
     179            0 :   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            0 : ml_tensors_info_create_extended (ml_tensors_info_h * info)
     187              : {
     188            0 :   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            0 : ml_tensors_info_destroy (ml_tensors_info_h info)
     196              : {
     197              :   ml_tensors_info_s *tensors_info;
     198              : 
     199            0 :   check_feature_state (ML_FEATURE);
     200              : 
     201            0 :   tensors_info = (ml_tensors_info_s *) info;
     202              : 
     203            0 :   if (!tensors_info)
     204            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     205              :         "The parameter, info, is NULL. Provide a valid pointer.");
     206              : 
     207            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     208            0 :   _ml_tensors_info_free (tensors_info);
     209            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     210              : 
     211            0 :   g_mutex_clear (&tensors_info->lock);
     212            0 :   g_free (tensors_info);
     213              : 
     214            0 :   return ML_ERROR_NONE;
     215              : }
     216              : 
     217              : /**
     218              :  * @brief Validates the given tensors info is valid.
     219              :  */
     220              : int
     221            0 : ml_tensors_info_validate (const ml_tensors_info_h info, bool *valid)
     222              : {
     223              :   ml_tensors_info_s *tensors_info;
     224              : 
     225            0 :   check_feature_state (ML_FEATURE);
     226              : 
     227            0 :   if (!valid)
     228            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     232              : 
     233            0 :   if (!tensors_info)
     234            0 :     _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            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     238            0 :   *valid = gst_tensors_info_validate (&tensors_info->info);
     239            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     240              : 
     241            0 :   return ML_ERROR_NONE;
     242              : }
     243              : 
     244              : /**
     245              :  * @brief Compares the given tensors information.
     246              :  */
     247              : int
     248            0 : _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            0 :   check_feature_state (ML_FEATURE);
     254              : 
     255            0 :   if (info1 == NULL)
     256            0 :     _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            0 :   if (info2 == NULL)
     259            0 :     _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            0 :   if (equal == NULL)
     262            0 :     _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            0 :   i1 = (ml_tensors_info_s *) info1;
     266            0 :   G_LOCK_UNLESS_NOLOCK (*i1);
     267            0 :   i2 = (ml_tensors_info_s *) info2;
     268            0 :   G_LOCK_UNLESS_NOLOCK (*i2);
     269              : 
     270            0 :   *equal = gst_tensors_info_is_equal (&i1->info, &i2->info);
     271              : 
     272            0 :   G_UNLOCK_UNLESS_NOLOCK (*i2);
     273            0 :   G_UNLOCK_UNLESS_NOLOCK (*i1);
     274            0 :   return ML_ERROR_NONE;
     275              : }
     276              : 
     277              : /**
     278              :  * @brief Sets the number of tensors with given handle of tensors information.
     279              :  */
     280              : int
     281            0 : ml_tensors_info_set_count (ml_tensors_info_h info, unsigned int count)
     282              : {
     283              :   ml_tensors_info_s *tensors_info;
     284              : 
     285            0 :   check_feature_state (ML_FEATURE);
     286              : 
     287            0 :   if (!info)
     288            0 :     _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            0 :   if (count > ML_TENSOR_SIZE_LIMIT || count == 0)
     291            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     296              : 
     297              :   /* This is atomic. No need for locks */
     298            0 :   tensors_info->info.num_tensors = count;
     299              : 
     300            0 :   return ML_ERROR_NONE;
     301              : }
     302              : 
     303              : /**
     304              :  * @brief Gets the number of tensors with given handle of tensors information.
     305              :  */
     306              : int
     307            0 : ml_tensors_info_get_count (ml_tensors_info_h info, unsigned int *count)
     308              : {
     309              :   ml_tensors_info_s *tensors_info;
     310              : 
     311            0 :   check_feature_state (ML_FEATURE);
     312              : 
     313            0 :   if (!info)
     314            0 :     _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            0 :   if (!count)
     317            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     321              :   /* This is atomic. No need for locks */
     322            0 :   *count = tensors_info->info.num_tensors;
     323              : 
     324            0 :   return ML_ERROR_NONE;
     325              : }
     326              : 
     327              : /**
     328              :  * @brief Sets the tensor name with given handle of tensors information.
     329              :  */
     330              : int
     331            0 : 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            0 :   check_feature_state (ML_FEATURE);
     338              : 
     339            0 :   if (!info)
     340            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     344            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     345              : 
     346            0 :   if (tensors_info->info.num_tensors <= index) {
     347            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     348            0 :     _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            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     354            0 :   if (!_info) {
     355            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     356            0 :     return ML_ERROR_INVALID_PARAMETER;
     357              :   }
     358              : 
     359            0 :   g_free (_info->name);
     360            0 :   _info->name = g_strdup (name);
     361              : 
     362            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     363            0 :   return ML_ERROR_NONE;
     364              : }
     365              : 
     366              : /**
     367              :  * @brief Gets the tensor name with given handle of tensors information.
     368              :  */
     369              : int
     370            0 : 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            0 :   check_feature_state (ML_FEATURE);
     377              : 
     378            0 :   if (!info)
     379            0 :     _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            0 :   if (!name)
     382            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     386            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     387              : 
     388            0 :   if (tensors_info->info.num_tensors <= index) {
     389            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     390            0 :     _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            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     396            0 :   if (!_info) {
     397            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     398            0 :     return ML_ERROR_INVALID_PARAMETER;
     399              :   }
     400              : 
     401            0 :   *name = g_strdup (_info->name);
     402              : 
     403            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     404            0 :   return ML_ERROR_NONE;
     405              : }
     406              : 
     407              : /**
     408              :  * @brief Sets the tensor type with given handle of tensors information.
     409              :  */
     410              : int
     411            0 : 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            0 :   check_feature_state (ML_FEATURE);
     418              : 
     419            0 :   if (!info)
     420            0 :     _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            0 :   if (type >= ML_TENSOR_TYPE_UNKNOWN || type < 0)
     424            0 :     _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            0 :   if (type == ML_TENSOR_TYPE_FLOAT16)
     430            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     436            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     437              : 
     438            0 :   if (tensors_info->info.num_tensors <= index) {
     439            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     440            0 :     _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            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     446            0 :   if (!_info) {
     447            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     448            0 :     return ML_ERROR_INVALID_PARAMETER;
     449              :   }
     450              : 
     451            0 :   _info->type = convert_tensor_type_from (type);
     452              : 
     453            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     454            0 :   return ML_ERROR_NONE;
     455              : }
     456              : 
     457              : /**
     458              :  * @brief Gets the tensor type with given handle of tensors information.
     459              :  */
     460              : int
     461            0 : 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            0 :   check_feature_state (ML_FEATURE);
     468              : 
     469            0 :   if (!info)
     470            0 :     _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            0 :   if (!type)
     473            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     477            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     478              : 
     479            0 :   if (tensors_info->info.num_tensors <= index) {
     480            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     481            0 :     _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            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     487            0 :   if (!_info) {
     488            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     489            0 :     return ML_ERROR_INVALID_PARAMETER;
     490              :   }
     491              : 
     492            0 :   *type = convert_ml_tensor_type_from (_info->type);
     493              : 
     494            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     495            0 :   return ML_ERROR_NONE;
     496              : }
     497              : 
     498              : /**
     499              :  * @brief Sets the tensor dimension with given handle of tensors information.
     500              :  */
     501              : int
     502            0 : 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            0 :   check_feature_state (ML_FEATURE);
     510              : 
     511            0 :   if (!info)
     512            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     516            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     517              : 
     518            0 :   if (tensors_info->info.num_tensors <= index) {
     519            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     520            0 :     _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            0 :   max_rank = tensors_info->is_extended ?
     531            0 :       ML_TENSOR_RANK_LIMIT : ML_TENSOR_RANK_LIMIT_PREV;
     532            0 :   rank = max_rank + 1;
     533            0 :   for (i = 0; i < max_rank; i++) {
     534            0 :     if (dimension[i] == 0) {
     535            0 :       if (rank > max_rank)
     536            0 :         rank = i;
     537              :     }
     538              : 
     539            0 :     if (rank == 0 || (i > rank && dimension[i] > 0)) {
     540            0 :       G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     541            0 :       _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            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     547            0 :   if (!_info) {
     548            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     549            0 :     return ML_ERROR_INVALID_PARAMETER;
     550              :   }
     551              : 
     552            0 :   for (i = 0; i < ML_TENSOR_RANK_LIMIT_PREV; i++) {
     553            0 :     _info->dimension[i] = dimension[i];
     554              :   }
     555              : 
     556            0 :   for (i = ML_TENSOR_RANK_LIMIT_PREV; i < ML_TENSOR_RANK_LIMIT; i++) {
     557            0 :     _info->dimension[i] = (tensors_info->is_extended ? dimension[i] : 0);
     558              :   }
     559              : 
     560            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     561            0 :   return ML_ERROR_NONE;
     562              : }
     563              : 
     564              : /**
     565              :  * @brief Gets the tensor dimension with given handle of tensors information.
     566              :  */
     567              : int
     568            0 : 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            0 :   guint i, valid_rank = ML_TENSOR_RANK_LIMIT;
     574              : 
     575            0 :   check_feature_state (ML_FEATURE);
     576              : 
     577            0 :   if (!info)
     578            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     582            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     583              : 
     584            0 :   if (tensors_info->info.num_tensors <= index) {
     585            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     586            0 :     _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            0 :   _info = gst_tensors_info_get_nth_info (&tensors_info->info, index);
     592            0 :   if (!_info) {
     593            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     594            0 :     return ML_ERROR_INVALID_PARAMETER;
     595              :   }
     596              : 
     597            0 :   if (!tensors_info->is_extended)
     598            0 :     valid_rank = ML_TENSOR_RANK_LIMIT_PREV;
     599              : 
     600            0 :   for (i = 0; i < valid_rank; i++) {
     601            0 :     dimension[i] = _info->dimension[i];
     602              :   }
     603              : 
     604            0 :   for (; i < ML_TENSOR_RANK_LIMIT; i++)
     605            0 :     dimension[i] = 0;
     606              : 
     607            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     608            0 :   return ML_ERROR_NONE;
     609              : }
     610              : 
     611              : /**
     612              :  * @brief Gets the byte size of the given handle of tensors information.
     613              :  */
     614              : int
     615            0 : 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            0 :   check_feature_state (ML_FEATURE);
     621              : 
     622            0 :   if (!info)
     623            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     624              :         "The parameter, info, is NULL. Provide a valid pointer.");
     625            0 :   if (!data_size)
     626            0 :     _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            0 :   tensors_info = (ml_tensors_info_s *) info;
     630            0 :   G_LOCK_UNLESS_NOLOCK (*tensors_info);
     631              : 
     632              :   /* init 0 */
     633            0 :   *data_size = 0;
     634              : 
     635            0 :   if (index >= 0 && tensors_info->info.num_tensors <= index) {
     636            0 :     G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     637            0 :     _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            0 :   *data_size = gst_tensors_info_get_size (&tensors_info->info, index);
     643              : 
     644            0 :   G_UNLOCK_UNLESS_NOLOCK (*tensors_info);
     645            0 :   return ML_ERROR_NONE;
     646              : }
     647              : 
     648              : /**
     649              :  * @brief Initializes the tensors information with default value.
     650              :  */
     651              : int
     652            0 : _ml_tensors_info_initialize (ml_tensors_info_s * info)
     653              : {
     654            0 :   if (!info)
     655            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
     656              :         "The parameter, info, is NULL. Provide a valid pointer.");
     657              : 
     658            0 :   gst_tensors_info_init (&info->info);
     659              : 
     660            0 :   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            0 : _ml_tensors_info_free (ml_tensors_info_s * info)
     669              : {
     670            0 :   if (!info)
     671            0 :     return;
     672              : 
     673            0 :   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            0 : _ml_tensors_data_destroy_internal (ml_tensors_data_h data, gboolean free_data)
     684              : {
     685            0 :   int status = ML_ERROR_NONE;
     686              :   ml_tensors_data_s *_data;
     687              :   guint i;
     688              : 
     689            0 :   if (data == NULL)
     690            0 :     _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            0 :   _data = (ml_tensors_data_s *) data;
     694            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
     695              : 
     696            0 :   if (free_data) {
     697            0 :     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            0 :       for (i = 0; i < ML_TENSOR_SIZE_LIMIT; i++) {
     707            0 :         if (_data->tensors[i].data) {
     708            0 :           g_free (_data->tensors[i].data);
     709            0 :           _data->tensors[i].data = NULL;
     710              :         }
     711              :       }
     712              :     }
     713              :   }
     714              : 
     715            0 :   if (_data->info)
     716            0 :     ml_tensors_info_destroy (_data->info);
     717              : 
     718            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     719            0 :   g_mutex_clear (&_data->lock);
     720            0 :   g_free (_data);
     721            0 :   return status;
     722              : }
     723              : 
     724              : /**
     725              :  * @brief Frees the tensors data pointer.
     726              :  * @note This does not touch the lock
     727              :  */
     728              : int
     729            0 : ml_tensors_data_destroy (ml_tensors_data_h data)
     730              : {
     731              :   int ret;
     732            0 :   check_feature_state (ML_FEATURE);
     733            0 :   ret = _ml_tensors_data_destroy_internal (data, TRUE);
     734            0 :   if (ret != ML_ERROR_NONE)
     735            0 :     _ml_error_report_return_continue (ret,
     736              :         "Call to _ml_tensors_data_destroy_internal failed with %d", ret);
     737            0 :   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            0 : _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            0 :   int status = ML_ERROR_NONE;
     752              : 
     753            0 :   check_feature_state (ML_FEATURE);
     754              : 
     755            0 :   if (data == NULL)
     756            0 :     _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            0 :   *data = NULL;
     761              : 
     762            0 :   _data = g_new0 (ml_tensors_data_s, 1);
     763            0 :   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            0 :   g_mutex_init (&_data->lock);
     768              : 
     769            0 :   _info = (ml_tensors_info_s *) info;
     770            0 :   if (_info != NULL) {
     771            0 :     status = _ml_tensors_info_create_from (info, &_data->info);
     772            0 :     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            0 :     G_LOCK_UNLESS_NOLOCK (*_info);
     779            0 :     _data->num_tensors = _info->info.num_tensors;
     780            0 :     for (i = 0; i < _data->num_tensors; i++) {
     781            0 :       _data->tensors[i].size = gst_tensors_info_get_size (&_info->info, i);
     782            0 :       _data->tensors[i].data = NULL;
     783              :     }
     784            0 :     G_UNLOCK_UNLESS_NOLOCK (*_info);
     785              :   }
     786              : 
     787            0 : error:
     788            0 :   if (status == ML_ERROR_NONE) {
     789            0 :     *data = _data;
     790              :   } else {
     791            0 :     _ml_tensors_data_destroy_internal (_data, FALSE);
     792              :   }
     793              : 
     794            0 :   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            0 : _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            0 :   check_feature_state (ML_FEATURE);
     809              : 
     810            0 :   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            0 :   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            0 :   status = _ml_tensors_data_create_no_alloc (data_src->info,
     818              :       (ml_tensors_data_h *) & _data);
     819            0 :   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            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
     825              : 
     826            0 :   _data->num_tensors = data_src->num_tensors;
     827            0 :   memcpy (_data->tensors, data_src->tensors,
     828            0 :       sizeof (GstTensorMemory) * data_src->num_tensors);
     829              : 
     830            0 :   *data = _data;
     831            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     832            0 :   return ML_ERROR_NONE;
     833              : }
     834              : 
     835              : /**
     836              :  * @brief Copies the tensor data frame.
     837              :  */
     838              : int
     839            0 : 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            0 :   check_feature_state (ML_FEATURE);
     846              : 
     847            0 :   if (in == NULL)
     848            0 :     _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            0 :   if (out == NULL)
     852            0 :     _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            0 :   _in = (ml_tensors_data_s *) in;
     856            0 :   G_LOCK_UNLESS_NOLOCK (*_in);
     857              : 
     858            0 :   status = ml_tensors_data_create (_in->info, out);
     859            0 :   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            0 :   _out = (ml_tensors_data_s *) (*out);
     865              : 
     866            0 :   for (i = 0; i < _out->num_tensors; ++i) {
     867            0 :     memcpy (_out->tensors[i].data, _in->tensors[i].data, _in->tensors[i].size);
     868              :   }
     869              : 
     870            0 : error:
     871            0 :   G_UNLOCK_UNLESS_NOLOCK (*_in);
     872            0 :   return status;
     873              : }
     874              : 
     875              : /**
     876              :  * @brief Gets the tensors information of given tensor data frame.
     877              :  */
     878              : int
     879            0 : 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            0 :   check_feature_state (ML_FEATURE);
     886              : 
     887            0 :   if (data == NULL) {
     888            0 :     _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            0 :   if (info == NULL) {
     893            0 :     _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            0 :   _data = (ml_tensors_data_s *) data;
     898            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
     899              : 
     900            0 :   status = _ml_tensors_info_create_from (_data->info, info);
     901            0 :   if (status != ML_ERROR_NONE) {
     902            0 :     _ml_error_report_continue
     903              :         ("Failed to get the tensor information from data handle.");
     904              :   }
     905              : 
     906            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
     907            0 :   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            0 : ml_tensors_data_create (const ml_tensors_info_h info, ml_tensors_data_h * data)
     915              : {
     916            0 :   gint status = ML_ERROR_STREAMS_PIPE;
     917            0 :   ml_tensors_data_s *_data = NULL;
     918              :   guint i;
     919              :   bool valid;
     920              : 
     921            0 :   check_feature_state (ML_FEATURE);
     922              : 
     923            0 :   if (info == NULL)
     924            0 :     _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            0 :   if (data == NULL)
     927            0 :     _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            0 :   status = ml_tensors_info_validate (info, &valid);
     931            0 :   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            0 :   if (!valid)
     935            0 :     _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            0 :       _ml_tensors_data_create_no_alloc (info, (ml_tensors_data_h *) & _data);
     940              : 
     941            0 :   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            0 :   for (i = 0; i < _data->num_tensors; i++) {
     948            0 :     _data->tensors[i].data = g_malloc0 (_data->tensors[i].size);
     949            0 :     if (_data->tensors[i].data == NULL) {
     950            0 :       goto failed_oom;
     951              :     }
     952              :   }
     953              : 
     954            0 :   *data = _data;
     955            0 :   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            0 : 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            0 :   int status = ML_ERROR_NONE;
     973              : 
     974            0 :   check_feature_state (ML_FEATURE);
     975              : 
     976            0 :   if (data == NULL)
     977            0 :     _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            0 :   if (raw_data == NULL)
     980            0 :     _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            0 :   if (data_size == NULL)
     983            0 :     _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            0 :   _data = (ml_tensors_data_s *) data;
     987            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
     988              : 
     989            0 :   if (_data->num_tensors <= index) {
     990            0 :     _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            0 :     status = ML_ERROR_INVALID_PARAMETER;
     994            0 :     goto report;
     995              :   }
     996              : 
     997            0 :   *raw_data = _data->tensors[index].data;
     998            0 :   *data_size = _data->tensors[index].size;
     999              : 
    1000            0 : report:
    1001            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1002            0 :   return status;
    1003              : }
    1004              : 
    1005              : /**
    1006              :  * @brief Copies a tensor data to given handle.
    1007              :  */
    1008              : int
    1009            0 : 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            0 :   int status = ML_ERROR_NONE;
    1014              : 
    1015            0 :   check_feature_state (ML_FEATURE);
    1016              : 
    1017            0 :   if (data == NULL)
    1018            0 :     _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            0 :   if (raw_data == NULL)
    1021            0 :     _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            0 :   _data = (ml_tensors_data_s *) data;
    1026            0 :   G_LOCK_UNLESS_NOLOCK (*_data);
    1027              : 
    1028            0 :   if (_data->num_tensors <= index) {
    1029            0 :     _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            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1033            0 :     goto report;
    1034              :   }
    1035              : 
    1036            0 :   if (data_size <= 0 || _data->tensors[index].size < data_size) {
    1037            0 :     _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            0 :     status = ML_ERROR_INVALID_PARAMETER;
    1041            0 :     goto report;
    1042              :   }
    1043              : 
    1044            0 :   if (_data->tensors[index].data != raw_data)
    1045            0 :     memcpy (_data->tensors[index].data, raw_data, data_size);
    1046              : 
    1047            0 : report:
    1048            0 :   G_UNLOCK_UNLESS_NOLOCK (*_data);
    1049            0 :   return status;
    1050              : }
    1051              : 
    1052              : /**
    1053              :  * @brief Copies tensor meta info.
    1054              :  */
    1055              : int
    1056            0 : 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            0 :   int status = ML_ERROR_NONE;
    1060              : 
    1061            0 :   check_feature_state (ML_FEATURE);
    1062              : 
    1063            0 :   dest_info = (ml_tensors_info_s *) dest;
    1064            0 :   src_info = (ml_tensors_info_s *) src;
    1065              : 
    1066            0 :   if (!dest_info)
    1067            0 :     _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            0 :   if (!src_info)
    1070            0 :     _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            0 :   G_LOCK_UNLESS_NOLOCK (*dest_info);
    1074            0 :   G_LOCK_UNLESS_NOLOCK (*src_info);
    1075              : 
    1076            0 :   if (gst_tensors_info_validate (&src_info->info)) {
    1077            0 :     dest_info->is_extended = src_info->is_extended;
    1078            0 :     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            0 :   G_UNLOCK_UNLESS_NOLOCK (*src_info);
    1087            0 :   G_UNLOCK_UNLESS_NOLOCK (*dest_info);
    1088              : 
    1089            0 :   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            0 : _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            0 :   guint changed = 0;
    1110              :   gsize len;
    1111              : 
    1112            0 :   g_return_val_if_fail (source, NULL);
    1113            0 :   g_return_val_if_fail (what && to, source);
    1114              : 
    1115            0 :   len = strlen (what);
    1116            0 :   start = source;
    1117              : 
    1118            0 :   builder = g_string_new (NULL);
    1119            0 :   while ((pos = g_strstr_len (start, -1, what)) != NULL) {
    1120            0 :     gboolean skip = FALSE;
    1121              : 
    1122            0 :     if (delimiters) {
    1123              :       const gchar *s;
    1124              :       gchar *prev, *next;
    1125              :       gboolean prev_split, next_split;
    1126              : 
    1127            0 :       prev = next = NULL;
    1128            0 :       prev_split = next_split = FALSE;
    1129              : 
    1130            0 :       if (pos != source)
    1131            0 :         prev = pos - 1;
    1132            0 :       if (*(pos + len) != '\0')
    1133            0 :         next = pos + len;
    1134              : 
    1135            0 :       for (s = delimiters; *s != '\0'; ++s) {
    1136            0 :         if (!prev || *s == *prev)
    1137            0 :           prev_split = TRUE;
    1138            0 :         if (!next || *s == *next)
    1139            0 :           next_split = TRUE;
    1140            0 :         if (prev_split && next_split)
    1141            0 :           break;
    1142              :       }
    1143              : 
    1144            0 :       if (!prev_split || !next_split)
    1145            0 :         skip = TRUE;
    1146              :     }
    1147              : 
    1148            0 :     builder = g_string_append_len (builder, start, pos - start);
    1149              : 
    1150              :     /* replace string if found */
    1151            0 :     if (skip)
    1152            0 :       builder = g_string_append_len (builder, pos, len);
    1153              :     else
    1154            0 :       builder = g_string_append (builder, to);
    1155              : 
    1156            0 :     start = pos + len;
    1157            0 :     if (!skip)
    1158            0 :       changed++;
    1159              :   }
    1160              : 
    1161              :   /* append remains */
    1162            0 :   builder = g_string_append (builder, start);
    1163            0 :   result = g_string_free (builder, FALSE);
    1164              : 
    1165            0 :   if (count)
    1166            0 :     *count = changed;
    1167              : 
    1168            0 :   g_free (source);
    1169            0 :   return result;
    1170              : }
    1171              : 
    1172              : /**
    1173              :  * @brief error reporting infra
    1174              :  */
    1175              : #define _ML_ERRORMSG_LENGTH (4096U)
    1176              : static char errormsg[_ML_ERRORMSG_LENGTH] = { 0 };      /* one page limit */
    1177              : 
    1178              : static int reported = 0;
    1179              : G_LOCK_DEFINE_STATIC (errlock);
    1180              : 
    1181              : /**
    1182              :  * @brief public API function of error reporting.
    1183              :  */
    1184              : const char *
    1185            0 : ml_error (void)
    1186              : {
    1187            0 :   G_LOCK (errlock);
    1188            0 :   if (reported != 0) {
    1189            0 :     errormsg[0] = '\0';
    1190            0 :     reported = 0;
    1191              :   }
    1192            0 :   if (errormsg[0] == '\0') {
    1193            0 :     G_UNLOCK (errlock);
    1194            0 :     return NULL;
    1195              :   }
    1196              : 
    1197            0 :   reported = 1;
    1198              : 
    1199            0 :   G_UNLOCK (errlock);
    1200            0 :   return errormsg;
    1201              : }
    1202              : 
    1203              : /**
    1204              :  * @brief Internal interface to write messages for ml_error()
    1205              :  */
    1206              : void
    1207            0 : _ml_error_report_ (const char *fmt, ...)
    1208              : {
    1209              :   int n;
    1210              :   va_list arg_ptr;
    1211            0 :   G_LOCK (errlock);
    1212              : 
    1213            0 :   va_start (arg_ptr, fmt);
    1214            0 :   n = vsnprintf (errormsg, _ML_ERRORMSG_LENGTH, fmt, arg_ptr);
    1215            0 :   va_end (arg_ptr);
    1216              : 
    1217            0 :   if (n > _ML_ERRORMSG_LENGTH) {
    1218            0 :     errormsg[_ML_ERRORMSG_LENGTH - 2] = '.';
    1219            0 :     errormsg[_ML_ERRORMSG_LENGTH - 3] = '.';
    1220            0 :     errormsg[_ML_ERRORMSG_LENGTH - 4] = '.';
    1221              :   }
    1222              : 
    1223            0 :   _ml_loge ("%s", errormsg);
    1224              : 
    1225            0 :   reported = 0;
    1226              : 
    1227            0 :   G_UNLOCK (errlock);
    1228            0 : }
    1229              : 
    1230              : /**
    1231              :  * @brief Internal interface to write messages for ml_error(), relaying previously reported errors.
    1232              :  */
    1233              : void
    1234            0 : _ml_error_report_continue_ (const char *fmt, ...)
    1235              : {
    1236            0 :   size_t cursor = 0;
    1237              :   va_list arg_ptr;
    1238              :   char buf[_ML_ERRORMSG_LENGTH];
    1239            0 :   G_LOCK (errlock);
    1240              : 
    1241              :   /* Check if there is a message to relay */
    1242            0 :   if (reported == 0) {
    1243            0 :     cursor = strlen (errormsg);
    1244            0 :     if (cursor < (_ML_ERRORMSG_LENGTH - 1)) {
    1245            0 :       errormsg[cursor] = '\n';
    1246            0 :       errormsg[cursor + 1] = '\0';
    1247            0 :       cursor++;
    1248              :     }
    1249              :   } else {
    1250            0 :     errormsg[0] = '\0';
    1251              :   }
    1252              : 
    1253            0 :   va_start (arg_ptr, fmt);
    1254            0 :   vsnprintf (buf, _ML_ERRORMSG_LENGTH - 1, fmt, arg_ptr);
    1255            0 :   _ml_loge ("%s", buf);
    1256              : 
    1257            0 :   memcpy (errormsg + cursor, buf, _ML_ERRORMSG_LENGTH - strlen (errormsg) - 1);
    1258            0 :   if (strlen (errormsg) >= (_ML_ERRORMSG_LENGTH - 2)) {
    1259            0 :     errormsg[_ML_ERRORMSG_LENGTH - 2] = '.';
    1260            0 :     errormsg[_ML_ERRORMSG_LENGTH - 3] = '.';
    1261            0 :     errormsg[_ML_ERRORMSG_LENGTH - 4] = '.';
    1262              :   }
    1263              : 
    1264            0 :   va_end (arg_ptr);
    1265              : 
    1266            0 :   errormsg[_ML_ERRORMSG_LENGTH - 1] = '\0';
    1267            0 :   reported = 0;
    1268            0 :   G_UNLOCK (errlock);
    1269            0 : }
    1270              : 
    1271              : static const char *strerrors[] = {
    1272              :   [0] = "Not an error",
    1273              :   [EINVAL] =
    1274              :       "Invalid parameters are given to a function. Check parameter values. (EINVAL)",
    1275              : };
    1276              : 
    1277              : /**
    1278              :  * @brief public API function of error code descriptions
    1279              :  */
    1280              : const char *
    1281            0 : ml_strerror (int errnum)
    1282              : {
    1283            0 :   int size = sizeof (strerrors) / sizeof (strerrors[0]);
    1284              : 
    1285            0 :   if (errnum < 0)
    1286            0 :     errnum = errnum * -1;
    1287              : 
    1288            0 :   if (errnum == 0 || errnum >= size)
    1289            0 :     return NULL;
    1290            0 :   return strerrors[errnum];
    1291              : }
    1292              : 
    1293              : /**
    1294              :  * @brief Internal function to check the handle is valid.
    1295              :  */
    1296              : static bool
    1297            0 : _ml_info_is_valid (gpointer handle, ml_info_type_e expected)
    1298              : {
    1299              :   ml_info_type_e current;
    1300              : 
    1301            0 :   if (!handle)
    1302            0 :     return false;
    1303              : 
    1304              :   /* The first field should be an enum value of ml_info_type_e. */
    1305            0 :   current = *((ml_info_type_e *) handle);
    1306            0 :   if (current != expected)
    1307            0 :     return false;
    1308              : 
    1309            0 :   switch (current) {
    1310            0 :     case ML_INFO_TYPE_OPTION:
    1311              :     case ML_INFO_TYPE_INFORMATION:
    1312              :     {
    1313            0 :       ml_info_s *_info = (ml_info_s *) handle;
    1314              : 
    1315            0 :       if (!_info->table)
    1316            0 :         return false;
    1317              : 
    1318            0 :       break;
    1319              :     }
    1320            0 :     case ML_INFO_TYPE_INFORMATION_LIST:
    1321            0 :       break;
    1322            0 :     default:
    1323              :       /* Unknown type */
    1324            0 :       return false;
    1325              :   }
    1326              : 
    1327            0 :   return true;
    1328              : }
    1329              : 
    1330              : /**
    1331              :  * @brief Internal function for destroy value of option table
    1332              :  */
    1333              : static void
    1334            0 : _ml_info_value_free (gpointer data)
    1335              : {
    1336              :   ml_info_value_s *_value;
    1337              : 
    1338            0 :   _value = (ml_info_value_s *) data;
    1339            0 :   if (_value) {
    1340            0 :     if (_value->destroy)
    1341            0 :       _value->destroy (_value->value);
    1342            0 :     g_free (_value);
    1343              :   }
    1344            0 : }
    1345              : 
    1346              : /**
    1347              :  * @brief Internal function for create ml_info
    1348              :  */
    1349              : static ml_info_s *
    1350            0 : _ml_info_create (ml_info_type_e type)
    1351              : {
    1352              :   ml_info_s *info;
    1353              : 
    1354            0 :   info = g_new0 (ml_info_s, 1);
    1355            0 :   if (info == NULL) {
    1356            0 :     _ml_error_report
    1357              :         ("Failed to allocate memory for the ml_info. Out of memory?");
    1358            0 :     return NULL;
    1359              :   }
    1360              : 
    1361            0 :   info->type = type;
    1362            0 :   info->table =
    1363            0 :       g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
    1364              :       _ml_info_value_free);
    1365            0 :   if (info->table == NULL) {
    1366            0 :     _ml_error_report
    1367              :         ("Failed to allocate memory for the table of ml_info. Out of memory?");
    1368            0 :     g_free (info);
    1369            0 :     return NULL;
    1370              :   }
    1371              : 
    1372            0 :   return info;
    1373              : }
    1374              : 
    1375              : /**
    1376              :  * @brief Internal function for destroy ml_info
    1377              :  */
    1378              : static void
    1379            0 : _ml_info_destroy (gpointer data)
    1380              : {
    1381            0 :   ml_info_s *info = (ml_info_s *) data;
    1382              : 
    1383            0 :   if (!info)
    1384            0 :     return;
    1385              : 
    1386            0 :   info->type = ML_INFO_TYPE_UNKNOWN;
    1387              : 
    1388            0 :   if (info->table) {
    1389            0 :     g_hash_table_destroy (info->table);
    1390            0 :     info->table = NULL;
    1391              :   }
    1392              : 
    1393            0 :   g_free (info);
    1394            0 :   return;
    1395              : }
    1396              : 
    1397              : /**
    1398              :  * @brief Internal function for set value of given ml_info
    1399              :  */
    1400              : static int
    1401            0 : _ml_info_set_value (ml_info_s * info, const char *key, void *value,
    1402              :     ml_data_destroy_cb destroy)
    1403              : {
    1404              :   ml_info_value_s *info_value;
    1405              : 
    1406            0 :   if (!STR_IS_VALID (key))
    1407            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1408              :         "The parameter, 'key' is invalid. It should be a valid string.");
    1409              : 
    1410            0 :   if (!info || !value)
    1411            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1412              :         "The parameter, 'info' or 'value' is NULL. It should be a valid ml_info and value.");
    1413              : 
    1414            0 :   info_value = g_new0 (ml_info_value_s, 1);
    1415            0 :   if (!info_value)
    1416            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1417              :         "Failed to allocate memory for the info value. Out of memory?");
    1418              : 
    1419            0 :   info_value->value = value;
    1420            0 :   info_value->destroy = destroy;
    1421            0 :   g_hash_table_insert (info->table, g_strdup (key), (gpointer) info_value);
    1422              : 
    1423            0 :   return ML_ERROR_NONE;
    1424              : }
    1425              : 
    1426              : /**
    1427              :  * @brief Internal function for get value of given ml_info
    1428              :  */
    1429              : static int
    1430            0 : _ml_info_get_value (ml_info_s * info, const char *key, void **value)
    1431              : {
    1432              :   ml_info_value_s *info_value;
    1433              : 
    1434            0 :   if (!info || !key || !value)
    1435            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1436              :         "The parameter, 'info', 'key' or 'value' is NULL. It should be a valid ml_info, key and value.");
    1437              : 
    1438            0 :   info_value = g_hash_table_lookup (info->table, key);
    1439            0 :   if (!info_value)
    1440            0 :     return ML_ERROR_INVALID_PARAMETER;
    1441              : 
    1442            0 :   *value = info_value->value;
    1443              : 
    1444            0 :   return ML_ERROR_NONE;
    1445              : }
    1446              : 
    1447              : /**
    1448              :  * @brief Creates an option and returns the instance a handle.
    1449              :  */
    1450              : int
    1451            0 : ml_option_create (ml_option_h * option)
    1452              : {
    1453            0 :   ml_info_s *_option = NULL;
    1454              : 
    1455            0 :   check_feature_state (ML_FEATURE);
    1456              : 
    1457            0 :   if (!option) {
    1458            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1459              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h");
    1460              :   }
    1461              : 
    1462            0 :   _option = _ml_info_create (ML_INFO_TYPE_OPTION);
    1463            0 :   if (_option == NULL)
    1464            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1465              :         "Failed to allocate memory for the option handle. Out of memory?");
    1466              : 
    1467            0 :   *option = _option;
    1468            0 :   return ML_ERROR_NONE;
    1469              : }
    1470              : 
    1471              : /**
    1472              :  * @brief Frees the given handle of a ml_option.
    1473              :  */
    1474              : int
    1475            0 : ml_option_destroy (ml_option_h option)
    1476              : {
    1477            0 :   check_feature_state (ML_FEATURE);
    1478              : 
    1479            0 :   if (!option) {
    1480            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1481              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1482              :   }
    1483              : 
    1484            0 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1485            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1486              :         "The parameter, 'option' is not a ml-option handle.");
    1487              : 
    1488            0 :   _ml_info_destroy (option);
    1489              : 
    1490            0 :   return ML_ERROR_NONE;
    1491              : }
    1492              : 
    1493              : /**
    1494              :  * @brief Set key-value pair in given option handle. Note that if duplicated key is given, the value is updated with the new one.
    1495              :  * If some options are changed or there are newly added options, please modify below description.
    1496              :  * The list of valid key-values are:
    1497              :  *
    1498              :  * key (char *)     || value (expected type (pointer))
    1499              :  * ---------------------------------------------------------
    1500              :  * "framework_name" ||  explicit name of framework (char *)
    1501              :  * ...
    1502              :  */
    1503              : int
    1504            0 : ml_option_set (ml_option_h option, const char *key, void *value,
    1505              :     ml_data_destroy_cb destroy)
    1506              : {
    1507            0 :   check_feature_state (ML_FEATURE);
    1508              : 
    1509            0 :   if (!option) {
    1510            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1511              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1512              :   }
    1513              : 
    1514            0 :   if (!key) {
    1515            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1516              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1517              :   }
    1518              : 
    1519            0 :   if (!value) {
    1520            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1521              :         "The parameter, 'value' is NULL. It should be a valid void*");
    1522              :   }
    1523              : 
    1524            0 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1525            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1526              :         "The parameter, 'option' is not a ml-option handle.");
    1527              : 
    1528            0 :   return _ml_info_set_value ((ml_info_s *) option, key, value, destroy);
    1529              : }
    1530              : 
    1531              : /**
    1532              :  * @brief Gets a value of key in ml_option instance.
    1533              :  */
    1534              : int
    1535            0 : ml_option_get (ml_option_h option, const char *key, void **value)
    1536              : {
    1537            0 :   check_feature_state (ML_FEATURE);
    1538              : 
    1539            0 :   if (!option) {
    1540            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1541              :         "The parameter, 'option' is NULL. It should be a valid ml_option_h, which should be created by ml_option_create().");
    1542              :   }
    1543              : 
    1544            0 :   if (!key) {
    1545            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1546              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1547              :   }
    1548              : 
    1549            0 :   if (!value) {
    1550            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1551              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1552              :   }
    1553              : 
    1554            0 :   if (!_ml_info_is_valid (option, ML_INFO_TYPE_OPTION))
    1555            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1556              :         "The parameter, 'option' is not a ml-option handle.");
    1557              : 
    1558            0 :   return _ml_info_get_value ((ml_info_s *) option, key, value);
    1559              : }
    1560              : 
    1561              : /**
    1562              :  * @brief Creates an ml_information instance and returns the handle.
    1563              :  */
    1564              : int
    1565            0 : _ml_information_create (ml_information_h * info)
    1566              : {
    1567            0 :   ml_info_s *_info = NULL;
    1568              : 
    1569            0 :   check_feature_state (ML_FEATURE);
    1570              : 
    1571            0 :   if (!info) {
    1572            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1573              :         "The parameter, 'info' is NULL. It should be a valid ml_information_h");
    1574              :   }
    1575              : 
    1576            0 :   _info = _ml_info_create (ML_INFO_TYPE_INFORMATION);
    1577            0 :   if (!_info)
    1578            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1579              :         "Failed to allocate memory for the info handle. Out of memory?");
    1580              : 
    1581            0 :   *info = _info;
    1582            0 :   return ML_ERROR_NONE;
    1583              : }
    1584              : 
    1585              : /**
    1586              :  * @brief Set key-value pair in given information handle.
    1587              :  * @note If duplicated key is given, the value is updated with the new one.
    1588              :  */
    1589              : int
    1590            0 : _ml_information_set (ml_information_h information, const char *key, void *value,
    1591              :     ml_data_destroy_cb destroy)
    1592              : {
    1593            0 :   check_feature_state (ML_FEATURE);
    1594              : 
    1595            0 :   if (!information) {
    1596            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1597              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1598              :   }
    1599              : 
    1600            0 :   if (!key) {
    1601            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1602              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1603              :   }
    1604              : 
    1605            0 :   if (!value) {
    1606            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1607              :         "The parameter, 'value' is NULL. It should be a valid void*");
    1608              :   }
    1609              : 
    1610            0 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1611            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1612              :         "The parameter, 'information' is not a ml-information handle.");
    1613              : 
    1614            0 :   return _ml_info_set_value ((ml_info_s *) information, key, value, destroy);
    1615              : }
    1616              : 
    1617              : /**
    1618              :  * @brief Frees the given handle of a ml_information.
    1619              :  */
    1620              : int
    1621            0 : ml_information_destroy (ml_information_h information)
    1622              : {
    1623            0 :   check_feature_state (ML_FEATURE);
    1624              : 
    1625            0 :   if (!information) {
    1626            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1627              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1628              :   }
    1629              : 
    1630            0 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1631            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1632              :         "The parameter, 'information' is not a ml-information handle.");
    1633              : 
    1634            0 :   _ml_info_destroy (information);
    1635              : 
    1636            0 :   return ML_ERROR_NONE;
    1637              : }
    1638              : 
    1639              : /**
    1640              :  * @brief Gets the value corresponding to the given key in ml_information instance.
    1641              :  */
    1642              : int
    1643            0 : ml_information_get (ml_information_h information, const char *key, void **value)
    1644              : {
    1645            0 :   check_feature_state (ML_FEATURE);
    1646              : 
    1647            0 :   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            0 :   if (!key) {
    1653            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1654              :         "The parameter, 'key' is NULL. It should be a valid const char*");
    1655              :   }
    1656              : 
    1657            0 :   if (!value) {
    1658            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1659              :         "The parameter, 'value' is NULL. It should be a valid void**");
    1660              :   }
    1661              : 
    1662            0 :   if (!_ml_info_is_valid (information, ML_INFO_TYPE_INFORMATION))
    1663            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1664              :         "The parameter, 'information' is not a ml-information handle.");
    1665              : 
    1666            0 :   return _ml_info_get_value ((ml_info_s *) information, key, value);
    1667              : }
    1668              : 
    1669              : /**
    1670              :  * @brief Creates an ml-information-list instance and returns the handle.
    1671              :  */
    1672              : int
    1673            0 : _ml_information_list_create (ml_information_list_h * list)
    1674              : {
    1675              :   ml_info_list_s *_info_list;
    1676              : 
    1677            0 :   check_feature_state (ML_FEATURE);
    1678              : 
    1679            0 :   if (!list)
    1680            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1681              :         "The parameter, 'list' is NULL. It should be a valid ml_information_list_h.");
    1682              : 
    1683            0 :   _info_list = g_try_new0 (ml_info_list_s, 1);
    1684            0 :   if (!_info_list) {
    1685            0 :     _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
    1686              :         "Failed to allocate memory for ml_information_list_h. Out of memory?");
    1687              :   }
    1688              : 
    1689            0 :   _info_list->type = ML_INFO_TYPE_INFORMATION_LIST;
    1690              : 
    1691            0 :   *list = _info_list;
    1692            0 :   return ML_ERROR_NONE;
    1693              : }
    1694              : 
    1695              : /**
    1696              :  * @brief Adds an ml-information into ml-information-list.
    1697              :  */
    1698              : int
    1699            0 : _ml_information_list_add (ml_information_list_h list, ml_information_h info)
    1700              : {
    1701              :   ml_info_list_s *_info_list;
    1702              : 
    1703            0 :   check_feature_state (ML_FEATURE);
    1704              : 
    1705            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1706            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1707              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1708              :   }
    1709              : 
    1710            0 :   if (!_ml_info_is_valid (info, ML_INFO_TYPE_OPTION) &&
    1711            0 :       !_ml_info_is_valid (info, ML_INFO_TYPE_INFORMATION)) {
    1712            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1713              :         "The parameter, 'info' is invalid. It should be a valid ml_information_h, which should be created by ml_information_create().");
    1714              :   }
    1715              : 
    1716            0 :   _info_list = (ml_info_list_s *) list;
    1717            0 :   _info_list->info = g_slist_append (_info_list->info, info);
    1718              : 
    1719            0 :   return ML_ERROR_NONE;
    1720              : }
    1721              : 
    1722              : /**
    1723              :  * @brief Destroys the ml-information-list instance.
    1724              :  */
    1725              : int
    1726            0 : ml_information_list_destroy (ml_information_list_h list)
    1727              : {
    1728              :   ml_info_list_s *_info_list;
    1729              : 
    1730            0 :   check_feature_state (ML_FEATURE);
    1731              : 
    1732            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1733            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1734              :         "The parameter, 'list' is invalid. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1735              :   }
    1736              : 
    1737            0 :   _info_list = (ml_info_list_s *) list;
    1738            0 :   g_slist_free_full (_info_list->info, _ml_info_destroy);
    1739            0 :   g_free (_info_list);
    1740              : 
    1741            0 :   return ML_ERROR_NONE;
    1742              : }
    1743              : 
    1744              : /**
    1745              :  * @brief Gets the number of ml-information in ml-information-list instance.
    1746              :  */
    1747              : int
    1748            0 : ml_information_list_length (ml_information_list_h list, unsigned int *length)
    1749              : {
    1750              :   ml_info_list_s *_info_list;
    1751              : 
    1752            0 :   check_feature_state (ML_FEATURE);
    1753              : 
    1754            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1755            0 :     _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            0 :   if (!length) {
    1760            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1761              :         "The parameter, 'length' is NULL. It should be a valid unsigned int*");
    1762              :   }
    1763              : 
    1764            0 :   _info_list = (ml_info_list_s *) list;
    1765            0 :   *length = g_slist_length (_info_list->info);
    1766              : 
    1767            0 :   return ML_ERROR_NONE;
    1768              : }
    1769              : 
    1770              : /**
    1771              :  * @brief Gets a ml-information in ml-information-list instance with given index.
    1772              :  */
    1773              : int
    1774            0 : ml_information_list_get (ml_information_list_h list, unsigned int index,
    1775              :     ml_information_h * information)
    1776              : {
    1777              :   ml_info_list_s *_info_list;
    1778              : 
    1779            0 :   check_feature_state (ML_FEATURE);
    1780              : 
    1781            0 :   if (!_ml_info_is_valid (list, ML_INFO_TYPE_INFORMATION_LIST)) {
    1782            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1783              :         "The parameter, 'list' is NULL. It should be a valid ml_information_list_h, which should be created by ml_information_list_create().");
    1784              :   }
    1785              : 
    1786            0 :   if (!information) {
    1787            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1788              :         "The parameter, 'information' is NULL. It should be a valid ml_information_h*");
    1789              :   }
    1790              : 
    1791            0 :   _info_list = (ml_info_list_s *) list;
    1792            0 :   *information = g_slist_nth_data (_info_list->info, index);
    1793              : 
    1794            0 :   if (*information == NULL) {
    1795            0 :     _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
    1796              :         "The parameter, 'index' is invalid. It should be less than the length of ml_information_list_h.");
    1797              :   }
    1798              : 
    1799            0 :   return ML_ERROR_NONE;
    1800              : }
        

Generated by: LCOV version 2.0-1