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