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