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