Coverage Report

Created: 2025-10-13 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/S2OPC/src/ClientServer/services/b2c/util_variant.c
Line
Count
Source
1
/*
2
 * Licensed to Systerel under one or more contributor license
3
 * agreements. See the NOTICE file distributed with this work
4
 * for additional information regarding copyright ownership.
5
 * Systerel licenses this file to you under the Apache
6
 * License, Version 2.0 (the "License"); you may not use this
7
 * file except in compliance with the License. You may obtain
8
 * a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
20
#include <inttypes.h>
21
#include <stdio.h>
22
#include <string.h>
23
24
#include "constants_statuscodes_bs.h"
25
#include "opcua_statuscodes.h"
26
#include "sopc_assert.h"
27
#include "sopc_macros.h"
28
#include "sopc_mem_alloc.h"
29
#include "util_b2c.h"
30
#include "util_variant.h"
31
32
#include "sopc_missing_c99.h"
33
34
SOPC_Variant* util_variant__new_Variant_from_NodeId(SOPC_NodeId* pnid, bool deepCopy)
35
0
{
36
0
    SOPC_Variant* pvar = SOPC_Variant_Create();
37
38
0
    if (NULL == pvar)
39
0
    {
40
0
        return NULL;
41
0
    }
42
43
0
    pvar->BuiltInTypeId = SOPC_NodeId_Id;
44
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
45
0
    if (deepCopy)
46
0
    {
47
0
        pvar->Value.NodeId = SOPC_Calloc(sizeof(*pvar->Value.NodeId), 1);
48
0
        SOPC_ReturnStatus status = (NULL != pvar->Value.NodeId ? SOPC_STATUS_OK : SOPC_STATUS_OUT_OF_MEMORY);
49
0
        if (SOPC_STATUS_OK == status)
50
0
        {
51
0
            status = SOPC_NodeId_Copy(pvar->Value.NodeId, pnid);
52
0
            if (SOPC_STATUS_OK != status)
53
0
            {
54
0
                SOPC_Free(pvar->Value.NodeId);
55
0
            }
56
0
        }
57
0
        if (SOPC_STATUS_OK != status)
58
0
        {
59
0
            SOPC_Free(pvar);
60
0
            pvar = NULL;
61
0
        }
62
0
    }
63
0
    else
64
0
    {
65
0
        pvar->Value.NodeId = pnid;
66
0
        pvar->DoNotClear = true; // It is shallow copy of provided node
67
0
    }
68
0
    return pvar;
69
0
}
70
71
SOPC_Variant* util_variant__new_Variant_from_NodeClass(OpcUa_NodeClass ncl)
72
0
{
73
0
    SOPC_Variant* pvar = SOPC_Malloc(sizeof(SOPC_Variant));
74
75
0
    if (NULL == pvar)
76
0
        return NULL;
77
78
0
    SOPC_Variant_Initialize(pvar);
79
0
    pvar->BuiltInTypeId = SOPC_Int32_Id;
80
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
81
0
    pvar->Value.Int32 = (int32_t) ncl;
82
83
0
    return pvar;
84
0
}
85
86
SOPC_Variant* util_variant__new_Variant_from_QualifiedName(SOPC_QualifiedName* qn, bool deepCopy)
87
0
{
88
0
    SOPC_Variant* pvar = SOPC_Variant_Create();
89
0
    if (NULL == pvar)
90
0
    {
91
0
        return NULL;
92
0
    }
93
94
0
    pvar->BuiltInTypeId = SOPC_QualifiedName_Id;
95
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
96
0
    if (deepCopy)
97
0
    {
98
0
        pvar->Value.Qname = SOPC_Calloc(sizeof(*pvar->Value.Qname), 1);
99
0
        SOPC_ReturnStatus status = (NULL != pvar->Value.Qname ? SOPC_STATUS_OK : SOPC_STATUS_OUT_OF_MEMORY);
100
0
        if (SOPC_STATUS_OK == status)
101
0
        {
102
0
            status = SOPC_QualifiedName_Copy(pvar->Value.Qname, qn);
103
0
            if (SOPC_STATUS_OK != status)
104
0
            {
105
0
                SOPC_Free(pvar->Value.Qname);
106
0
            }
107
0
        }
108
0
        if (SOPC_STATUS_OK != status)
109
0
        {
110
0
            SOPC_Free(pvar);
111
0
            pvar = NULL;
112
0
        }
113
0
    }
114
0
    else
115
0
    {
116
0
        pvar->Value.Qname = qn;
117
0
        pvar->DoNotClear = true; // It is shallow copy of provided node
118
0
    }
119
120
0
    return pvar;
121
0
}
122
123
SOPC_Variant* util_variant__new_Variant_from_LocalizedText(SOPC_LocalizedText* lt, bool deepCopy)
124
0
{
125
0
    SOPC_Variant* pvar = SOPC_Variant_Create();
126
127
0
    if (NULL == pvar)
128
0
    {
129
0
        return NULL;
130
0
    }
131
132
0
    pvar->BuiltInTypeId = SOPC_LocalizedText_Id;
133
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
134
0
    if (deepCopy)
135
0
    {
136
0
        pvar->Value.LocalizedText = SOPC_Calloc(sizeof(*pvar->Value.LocalizedText), 1);
137
0
        SOPC_ReturnStatus status = (NULL != pvar->Value.LocalizedText ? SOPC_STATUS_OK : SOPC_STATUS_OUT_OF_MEMORY);
138
0
        if (SOPC_STATUS_OK == status)
139
0
        {
140
0
            status = SOPC_LocalizedText_Copy(pvar->Value.LocalizedText, lt);
141
0
            if (SOPC_STATUS_OK != status)
142
0
            {
143
0
                SOPC_Free(pvar->Value.LocalizedText);
144
0
            }
145
0
        }
146
0
        if (SOPC_STATUS_OK != status)
147
0
        {
148
0
            SOPC_Free(pvar);
149
0
            pvar = NULL;
150
0
        }
151
0
    }
152
0
    else
153
0
    {
154
0
        pvar->Value.LocalizedText = lt;
155
0
        pvar->DoNotClear = true; // It is shallow copy of provided node
156
0
    }
157
158
0
    return pvar;
159
0
}
160
161
SOPC_Variant* util_variant__new_Variant_from_RolePermissions(OpcUa_RolePermissionType* rolePermissionsArray,
162
                                                             int32_t noOfRolePermissions)
163
0
{
164
0
    SOPC_ASSERT(noOfRolePermissions > 0 && rolePermissionsArray != NULL);
165
166
0
    SOPC_Variant* pvar = SOPC_Variant_Create();
167
168
0
    if (NULL == pvar)
169
0
    {
170
0
        return NULL;
171
0
    }
172
173
0
    SOPC_ReturnStatus status = SOPC_STATUS_NOK;
174
0
    bool res = false;
175
176
    // Initialize variant and create extObjects.
177
0
    res = SOPC_Variant_Initialize_Array(pvar, SOPC_ExtensionObject_Id, noOfRolePermissions);
178
0
    if (res)
179
0
    {
180
        // Variant extensionObjects are now allocated.
181
0
        for (int32_t i = 0; i < noOfRolePermissions; i++)
182
0
        {
183
            // Create the encodeableObject that will be pointed by the extensionObjects in the variant.
184
0
            OpcUa_RolePermissionType* rolePerm = NULL;
185
0
            status = SOPC_ExtensionObject_CreateObject(&pvar->Value.Array.Content.ExtObjectArr[i],
186
0
                                                       &OpcUa_RolePermissionType_EncodeableType, (void**) &rolePerm);
187
0
            if (SOPC_STATUS_OK == status)
188
0
            {
189
0
                status = SOPC_EncodeableObject_Copy(&OpcUa_RolePermissionType_EncodeableType, (void*) rolePerm,
190
0
                                                    (const void*) &rolePermissionsArray[i]);
191
0
            }
192
0
        }
193
0
    }
194
0
    else
195
0
    {
196
0
        status = SOPC_STATUS_OUT_OF_MEMORY;
197
0
    }
198
199
0
    if (SOPC_STATUS_OK != status)
200
0
    {
201
0
        SOPC_Variant_Delete(pvar);
202
0
        pvar = NULL;
203
0
    }
204
205
0
    return pvar;
206
0
}
207
208
bool util_variant__copy_PreferredLocalizedText_from_LocalizedText_Variant(SOPC_Variant* dest,
209
                                                                          const SOPC_Variant* src,
210
                                                                          char** preferredLocales)
211
0
{
212
0
    SOPC_ASSERT(NULL != src);
213
0
    SOPC_ASSERT(NULL != dest);
214
0
    SOPC_ASSERT(NULL != preferredLocales);
215
216
0
    SOPC_ASSERT(SOPC_LocalizedText_Id == src->BuiltInTypeId);
217
218
0
    SOPC_Variant* srcCopy = SOPC_Variant_Create();
219
0
    if (NULL == srcCopy)
220
0
    {
221
0
        return false;
222
0
    }
223
0
    SOPC_ReturnStatus status = SOPC_Variant_ShallowCopy(srcCopy, src);
224
225
0
    if (SOPC_STATUS_OK == status)
226
0
    {
227
0
        bool success = false;
228
0
        srcCopy =
229
0
            util_variant__set_PreferredLocalizedText_from_LocalizedText_Variant(&srcCopy, preferredLocales, &success);
230
0
        status = (success ? SOPC_STATUS_OK : SOPC_STATUS_NOK);
231
0
    }
232
0
    if (SOPC_STATUS_OK == status)
233
0
    {
234
0
        *dest = *srcCopy;
235
0
    }
236
0
    SOPC_Free(srcCopy);
237
0
    return (SOPC_STATUS_OK == status);
238
0
}
239
240
SOPC_Variant* util_variant__set_PreferredLocalizedText_from_LocalizedText_Variant(SOPC_Variant** v,
241
                                                                                  char** preferredLocales,
242
                                                                                  bool* success)
243
0
{
244
0
    SOPC_ASSERT(NULL != v);
245
0
    SOPC_Variant* value = *v;
246
0
    SOPC_ASSERT(SOPC_LocalizedText_Id == value->BuiltInTypeId);
247
248
0
    bool res = false;
249
    // If the caller wants to know the final result.
250
0
    if (NULL != success)
251
0
    {
252
0
        *success = res;
253
0
    }
254
255
    // Create a variant that will be a deep copy of *v
256
0
    SOPC_Variant* result = SOPC_Variant_Create();
257
0
    if (NULL == result)
258
0
    {
259
0
        return value;
260
0
    }
261
262
0
    if (SOPC_VariantArrayType_SingleValue == value->ArrayType)
263
0
    {
264
0
        SOPC_LocalizedText* newLt = SOPC_Malloc(sizeof(*newLt));
265
0
        SOPC_LocalizedText_Initialize(newLt);
266
0
        SOPC_ReturnStatus status =
267
0
            SOPC_LocalizedText_GetPreferredLocale(newLt, preferredLocales, value->Value.LocalizedText);
268
0
        if (SOPC_STATUS_OK != status)
269
0
        {
270
0
            SOPC_Free(newLt);
271
0
            SOPC_Variant_Clear(result);
272
0
            SOPC_Free(result);
273
0
            result = value;
274
0
        }
275
0
        else
276
0
        {
277
0
            result->ArrayType = SOPC_VariantArrayType_SingleValue;
278
0
            result->BuiltInTypeId = SOPC_LocalizedText_Id;
279
0
            result->Value.LocalizedText = newLt;
280
0
            res = true;
281
0
            SOPC_Variant_Clear(value);
282
0
            SOPC_Free(value);
283
0
            *v = NULL;
284
0
        }
285
0
    }
286
0
    else if (SOPC_VariantArrayType_Array == value->ArrayType || SOPC_VariantArrayType_Matrix == value->ArrayType)
287
0
    {
288
0
        SOPC_ReturnStatus status = SOPC_Variant_Copy(result, value);
289
290
0
        if (SOPC_STATUS_OK == status)
291
0
        {
292
0
            int32_t length = SOPC_Variant_GetArrayOrMatrixLength(value);
293
0
            const SOPC_LocalizedText* dest = NULL;
294
0
            const SOPC_LocalizedText* src = NULL;
295
0
            for (int32_t i = 0; SOPC_STATUS_OK == status && i < length; i++)
296
0
            {
297
0
                dest = SOPC_Variant_Get_ArrayValue(result, SOPC_LocalizedText_Id, i);
298
0
                src = SOPC_Variant_Get_ArrayValue(value, SOPC_LocalizedText_Id, i);
299
0
                SOPC_GCC_DIAGNOSTIC_IGNORE_CAST_CONST
300
0
                SOPC_LocalizedText_Clear(
301
0
                    (SOPC_LocalizedText*) dest); // Clear the initial copy and retrieved preferred locale
302
0
                status = SOPC_LocalizedText_GetPreferredLocale((SOPC_LocalizedText*) dest, preferredLocales, src);
303
0
                SOPC_GCC_DIAGNOSTIC_RESTORE
304
0
            }
305
0
        }
306
307
0
        if (SOPC_STATUS_OK == status)
308
0
        {
309
            // Preferred localized text array created, remove source one
310
0
            res = true;
311
0
            SOPC_Variant_Clear(value);
312
0
            SOPC_Free(value);
313
0
            *v = NULL;
314
0
        }
315
0
        else
316
0
        {
317
            // Do not compute preferred localized texts and keep default ones
318
0
            SOPC_Variant_Clear(result);
319
0
            SOPC_Free(result);
320
0
            result = value;
321
0
        }
322
0
    }
323
0
    else
324
0
    {
325
0
        SOPC_ASSERT(false);
326
0
    }
327
328
    // Update final result status
329
0
    if (NULL != success)
330
0
    {
331
0
        *success = res;
332
0
    }
333
334
0
    return result;
335
0
}
336
337
SOPC_Variant* util_variant__new_Variant_from_Indet(void)
338
0
{
339
0
    SOPC_Variant* pvar = SOPC_Malloc(sizeof(SOPC_Variant));
340
341
0
    if (NULL == pvar)
342
0
        return NULL;
343
344
0
    SOPC_Variant_Initialize(pvar);
345
0
    pvar->BuiltInTypeId = SOPC_Null_Id;
346
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
347
348
0
    return pvar;
349
0
}
350
351
SOPC_Variant* util_variant__new_Variant_from_Variant(const SOPC_Variant* pvara, bool deepCopy)
352
0
{
353
0
    SOPC_ReturnStatus retStatus = SOPC_STATUS_OK;
354
0
    SOPC_Variant* pvar;
355
0
    if (NULL == pvara)
356
0
        return util_variant__new_Variant_from_Indet();
357
358
0
    pvar = SOPC_Variant_Create();
359
360
0
    if (NULL == pvar)
361
0
        return NULL;
362
363
0
    if (deepCopy)
364
0
    {
365
0
        retStatus = SOPC_Variant_Copy(pvar, pvara);
366
0
    }
367
0
    else
368
0
    {
369
0
        retStatus = SOPC_Variant_ShallowCopy(pvar, pvara);
370
0
    }
371
372
0
    if (retStatus != SOPC_STATUS_OK)
373
0
    {
374
0
        if (pvar != NULL)
375
0
        {
376
0
            SOPC_Free(pvar);
377
0
        }
378
0
        pvar = NULL;
379
0
    }
380
381
0
    return pvar;
382
0
}
383
384
SOPC_Variant* util_variant__new_Variant_from_Bool(bool b)
385
0
{
386
0
    SOPC_Variant* pvar = SOPC_Malloc(sizeof(SOPC_Variant));
387
388
0
    if (NULL != pvar)
389
0
    {
390
0
        SOPC_Variant_Initialize(pvar);
391
0
        pvar->BuiltInTypeId = SOPC_Boolean_Id;
392
0
        pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
393
0
        pvar->Value.Byte = b;
394
0
    }
395
396
0
    return pvar;
397
0
}
398
399
SOPC_Variant* util_variant__new_Variant_from_Byte(uint8_t i)
400
0
{
401
0
    SOPC_Variant* pvar = SOPC_Malloc(sizeof(SOPC_Variant));
402
403
0
    if (NULL != pvar)
404
0
    {
405
0
        SOPC_Variant_Initialize(pvar);
406
0
        pvar->BuiltInTypeId = SOPC_Byte_Id;
407
0
        pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
408
0
        pvar->Value.Byte = i;
409
0
    }
410
411
0
    return pvar;
412
0
}
413
414
SOPC_Variant* util_variant__new_Variant_from_uint32(uint32_t i)
415
0
{
416
0
    SOPC_Variant* pvar = SOPC_Malloc(sizeof(SOPC_Variant));
417
418
0
    if (NULL == pvar)
419
0
        return NULL;
420
421
0
    SOPC_Variant_Initialize(pvar);
422
0
    pvar->BuiltInTypeId = SOPC_UInt32_Id;
423
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
424
0
    pvar->Value.Uint32 = i;
425
426
0
    return pvar;
427
0
}
428
429
SOPC_Variant* util_variant__new_Variant_from_int64(int64_t i)
430
0
{
431
0
    SOPC_Variant* pvar = SOPC_Malloc(sizeof(SOPC_Variant));
432
433
0
    if (NULL == pvar)
434
0
        return NULL;
435
436
0
    SOPC_Variant_Initialize(pvar);
437
0
    pvar->BuiltInTypeId = SOPC_Int64_Id;
438
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
439
0
    pvar->Value.Int64 = i;
440
441
0
    return pvar;
442
0
}
443
444
SOPC_Variant* util_variant__new_Variant_from_int32(int32_t i)
445
0
{
446
0
    SOPC_Variant* pvar = SOPC_Malloc(sizeof(SOPC_Variant));
447
448
0
    if (NULL == pvar)
449
0
        return NULL;
450
451
0
    SOPC_Variant_Initialize(pvar);
452
0
    pvar->BuiltInTypeId = SOPC_Int32_Id;
453
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
454
0
    pvar->Value.Int32 = i;
455
456
0
    return pvar;
457
0
}
458
459
SOPC_Variant* util_variant__new_Variant_from_double(double f)
460
0
{
461
0
    SOPC_Variant* pvar = SOPC_Malloc(sizeof(SOPC_Variant));
462
463
0
    if (NULL == pvar)
464
0
        return NULL;
465
466
0
    SOPC_Variant_Initialize(pvar);
467
0
    pvar->BuiltInTypeId = SOPC_Double_Id;
468
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
469
0
    pvar->Value.Doublev = f;
470
471
0
    return pvar;
472
0
}
473
474
SOPC_Variant* util_variant__new_Variant_from_ByteString(SOPC_ByteString* bs, bool deepCopy)
475
0
{
476
0
    SOPC_ASSERT(NULL != bs);
477
0
    SOPC_Variant* pvar = SOPC_Variant_Create();
478
0
    if (NULL == pvar)
479
0
    {
480
0
        return NULL;
481
0
    }
482
483
0
    pvar->BuiltInTypeId = SOPC_ByteString_Id;
484
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
485
0
    if (deepCopy)
486
0
    {
487
0
        SOPC_ByteString_Initialize(&pvar->Value.Bstring);
488
0
        SOPC_ReturnStatus status = SOPC_ByteString_Copy(&pvar->Value.Bstring, bs);
489
0
        if (SOPC_STATUS_OK != status)
490
0
        {
491
0
            SOPC_Free(pvar);
492
0
            pvar = NULL;
493
0
        }
494
0
    }
495
0
    else
496
0
    {
497
0
        pvar->Value.Bstring = *bs;
498
0
        pvar->DoNotClear = true; // It is shallow copy of provided node
499
0
    }
500
501
0
    return pvar;
502
0
}
503
504
SOPC_Variant* util_variant__new_Variant_from_ExtensionObject(SOPC_ExtensionObject* extObj, bool deepCopy)
505
0
{
506
0
    SOPC_Variant* pvar = SOPC_Variant_Create();
507
508
0
    if (NULL == pvar)
509
0
        return NULL;
510
511
0
    pvar->BuiltInTypeId = SOPC_ExtensionObject_Id;
512
0
    pvar->ArrayType = SOPC_VariantArrayType_SingleValue;
513
0
    if (deepCopy)
514
0
    {
515
0
        pvar->Value.ExtObject = SOPC_Calloc(sizeof(*pvar->Value.ExtObject), 1);
516
0
        SOPC_ReturnStatus status = (NULL != pvar->Value.ExtObject ? SOPC_STATUS_OK : SOPC_STATUS_OUT_OF_MEMORY);
517
0
        if (SOPC_STATUS_OK == status)
518
0
        {
519
0
            status = SOPC_ExtensionObject_Copy(pvar->Value.ExtObject, extObj);
520
0
            if (SOPC_STATUS_OK != status)
521
0
            {
522
0
                SOPC_Free(pvar->Value.ExtObject);
523
0
            }
524
0
        }
525
0
        if (SOPC_STATUS_OK != status)
526
0
        {
527
0
            SOPC_Free(pvar);
528
0
            pvar = NULL;
529
0
        }
530
0
    }
531
0
    else
532
0
    {
533
0
        pvar->Value.ExtObject = extObj;
534
0
        pvar->DoNotClear = true; // It is shallow copy of provided node
535
0
    }
536
537
0
    return pvar;
538
0
}
539
540
SOPC_ReturnStatus util_variant__copy_and_apply_locales_and_index_range(SOPC_Variant* destVal,
541
                                                                       const SOPC_Variant* source,
542
                                                                       char** preferredLocalesIds,
543
                                                                       const SOPC_NumericRange* indexRange)
544
0
{
545
0
    SOPC_ASSERT(NULL != destVal);
546
0
    SOPC_ASSERT(NULL != source);
547
0
    SOPC_ReturnStatus status = SOPC_STATUS_OK;
548
0
    SOPC_Variant ltEventVar;
549
0
    SOPC_Variant_Initialize(&ltEventVar);
550
0
    SOPC_StatusCode valueStatus = SOPC_GoodGenericStatus;
551
552
    /* Set the preferred locale in case of LT value */
553
0
    if (SOPC_LocalizedText_Id == source->BuiltInTypeId && NULL != preferredLocalesIds)
554
0
    {
555
0
        bool res = util_variant__copy_PreferredLocalizedText_from_LocalizedText_Variant(&ltEventVar, source,
556
0
                                                                                        preferredLocalesIds);
557
0
        if (!res)
558
0
        {
559
0
            status = SOPC_STATUS_OUT_OF_MEMORY;
560
0
            valueStatus = OpcUa_BadOutOfMemory;
561
0
        }
562
0
        source = &ltEventVar;
563
0
    }
564
565
    /* IndexRange filtering */
566
0
    constants_statuscodes_bs__t_StatusCode_i readSC = constants_statuscodes_bs__c_StatusCode_indet;
567
0
    if (SOPC_STATUS_OK == status)
568
0
    {
569
0
        if (NULL != indexRange)
570
0
        {
571
0
            readSC = util_read_value_indexed_helper(destVal, source, indexRange);
572
0
            if (constants_statuscodes_bs__e_sc_ok != readSC)
573
0
            {
574
                /* note: index range syntax error shall have occurred on createMI but the specification state any error
575
                 * might be returned as value:
576
                 * "Servers should return all other errors as CreateMonitoredItems results
577
                 *  but all possible errors are allowed to be returned in the Publish response."
578
                 */
579
0
                util_status_code__B_to_C(readSC, &valueStatus);
580
0
                status = SOPC_STATUS_NOK;
581
0
            }
582
0
        }
583
0
        else
584
0
        {
585
0
            status = SOPC_Variant_Copy(destVal, source);
586
0
            if (SOPC_STATUS_OK != status)
587
0
            {
588
0
                SOPC_ASSERT(SOPC_STATUS_OUT_OF_MEMORY == status);
589
0
                valueStatus = OpcUa_BadOutOfMemory;
590
0
            }
591
0
        }
592
0
    }
593
594
0
    SOPC_Variant_Clear(&ltEventVar);
595
0
    if (SOPC_STATUS_OK != status)
596
0
    {
597
0
        SOPC_ASSERT(!SOPC_IsGoodStatus(valueStatus));
598
0
        SOPC_Variant_Clear(destVal);
599
0
        destVal->BuiltInTypeId = SOPC_StatusCode_Id;
600
0
        destVal->Value.Status = valueStatus;
601
0
    }
602
0
    return status;
603
0
}
604
605
SOPC_ReturnStatus util_variant__update_applying_supported_locales(SOPC_Variant* valToUpdate,
606
                                                                  const SOPC_Variant* newVal,
607
                                                                  char** supportedLocales)
608
0
{
609
0
    SOPC_ASSERT(NULL != valToUpdate);
610
0
    SOPC_ASSERT(NULL != newVal);
611
0
    SOPC_ASSERT(NULL != supportedLocales);
612
0
    SOPC_ReturnStatus status = SOPC_STATUS_OK;
613
614
0
    if (valToUpdate->ArrayType != newVal->ArrayType || SOPC_LocalizedText_Id != valToUpdate->BuiltInTypeId ||
615
0
        valToUpdate->BuiltInTypeId != newVal->BuiltInTypeId)
616
0
    {
617
0
        return SOPC_STATUS_INVALID_PARAMETERS;
618
0
    }
619
620
0
    if (SOPC_VariantArrayType_SingleValue == valToUpdate->ArrayType)
621
0
    {
622
0
        status = SOPC_LocalizedText_AddOrSetLocale(valToUpdate->Value.LocalizedText, supportedLocales,
623
0
                                                   newVal->Value.LocalizedText);
624
0
    }
625
0
    else if (SOPC_VariantArrayType_Array == valToUpdate->ArrayType)
626
0
    {
627
0
        SOPC_ASSERT(valToUpdate->Value.Array.Length == newVal->Value.Array.Length);
628
0
        for (int32_t i = 0; SOPC_STATUS_OK == status && i < newVal->Value.Array.Length; i++)
629
0
        {
630
0
            status =
631
0
                SOPC_LocalizedText_AddOrSetLocale(&valToUpdate->Value.Array.Content.LocalizedTextArr[i],
632
0
                                                  supportedLocales, &newVal->Value.Array.Content.LocalizedTextArr[i]);
633
0
        }
634
0
    }
635
0
    else if (SOPC_VariantArrayType_Matrix == valToUpdate->ArrayType)
636
0
    {
637
0
        SOPC_ASSERT(valToUpdate->Value.Matrix.Dimensions == newVal->Value.Matrix.Dimensions);
638
0
        int32_t matrixLength = 1;
639
0
        for (int32_t i = 0; i < newVal->Value.Matrix.Dimensions; i++)
640
0
        {
641
0
            SOPC_ASSERT(valToUpdate->Value.Matrix.ArrayDimensions[i] == newVal->Value.Matrix.ArrayDimensions[i]);
642
0
            matrixLength *= valToUpdate->Value.Matrix.ArrayDimensions[i];
643
0
        }
644
0
        for (int32_t i = 0; SOPC_STATUS_OK == status && i < matrixLength; i++)
645
0
        {
646
0
            status =
647
0
                SOPC_LocalizedText_AddOrSetLocale(&valToUpdate->Value.Matrix.Content.LocalizedTextArr[i],
648
0
                                                  supportedLocales, &newVal->Value.Matrix.Content.LocalizedTextArr[i]);
649
0
        }
650
0
    }
651
0
    else
652
0
    {
653
0
        status = SOPC_STATUS_INVALID_PARAMETERS;
654
0
    }
655
0
    return status;
656
0
}