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

Generated by: LCOV version 2.0-1