Coverage Report

Created: 2024-02-25 07:19

/src/libpff/libcdata/libcdata_btree.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Balanced tree type functions
3
 *
4
 * Copyright (C) 2006-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <memory.h>
24
#include <types.h>
25
26
#include "libcdata_array.h"
27
#include "libcdata_btree.h"
28
#include "libcdata_btree_node.h"
29
#include "libcdata_btree_values_list.h"
30
#include "libcdata_definitions.h"
31
#include "libcdata_libcerror.h"
32
#include "libcdata_libcthreads.h"
33
#include "libcdata_list.h"
34
#include "libcdata_list_element.h"
35
#include "libcdata_tree_node.h"
36
#include "libcdata_types.h"
37
38
/* Creates a tree
39
 * Make sure the value tree is referencing, is set to NULL
40
 * Returns 1 if successful or -1 on error
41
 */
42
int libcdata_btree_initialize(
43
     libcdata_btree_t **tree,
44
     int maximum_number_of_values,
45
     libcerror_error_t **error )
46
5.40k
{
47
5.40k
  libcdata_internal_btree_t *internal_tree = NULL;
48
5.40k
  static char *function                    = "libcdata_btree_initialize";
49
50
5.40k
  if( tree == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid tree.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
5.40k
  if( *tree != NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
66
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67
0
     "%s: invalid tree value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
5.40k
  if( maximum_number_of_values <= 0 )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
77
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
78
0
     "%s: invalid maximum number of values value out of bounds.",
79
0
     function );
80
81
0
    return( -1 );
82
0
  }
83
5.40k
  internal_tree = memory_allocate_structure(
84
5.40k
                   libcdata_internal_btree_t );
85
86
5.40k
  if( internal_tree == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
92
0
     "%s: unable to create tree.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
5.40k
  if( memory_set(
98
5.40k
       internal_tree,
99
5.40k
       0,
100
5.40k
       sizeof( libcdata_internal_btree_t ) ) == NULL )
101
0
  {
102
0
    libcerror_error_set(
103
0
     error,
104
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
105
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
106
0
     "%s: unable to clear tree.",
107
0
     function );
108
109
0
    memory_free(
110
0
     internal_tree );
111
112
0
    return( -1 );
113
0
  }
114
5.40k
  if( libcdata_array_initialize(
115
5.40k
       &( internal_tree->values_array ),
116
5.40k
       0,
117
5.40k
       error ) != 1 )
118
0
  {
119
0
    libcerror_error_set(
120
0
     error,
121
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
122
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
123
0
     "%s: unable to create values array.",
124
0
     function );
125
126
0
    goto on_error;
127
0
  }
128
5.40k
  if( libcdata_tree_node_initialize(
129
5.40k
       &( internal_tree->root_node ),
130
5.40k
       error ) != 1 )
131
0
  {
132
0
    libcerror_error_set(
133
0
     error,
134
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
135
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
136
0
     "%s: unable to create root node.",
137
0
     function );
138
139
0
    goto on_error;
140
0
  }
141
5.40k
  internal_tree->maximum_number_of_values = maximum_number_of_values;
142
143
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
144
  if( libcthreads_read_write_lock_initialize(
145
       &( internal_tree->read_write_lock ),
146
       error ) != 1 )
147
  {
148
    libcerror_error_set(
149
     error,
150
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
151
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
152
     "%s: unable to initialize read/write lock.",
153
     function );
154
155
    goto on_error;
156
  }
157
#endif
158
5.40k
  *tree = (libcdata_btree_t *) internal_tree;
159
160
5.40k
  return( 1 );
161
162
0
on_error:
163
0
  if( internal_tree != NULL )
164
0
  {
165
0
    if( internal_tree->values_array != NULL )
166
0
    {
167
0
      libcdata_array_free(
168
0
       &( internal_tree->values_array ),
169
0
       NULL,
170
0
       NULL );
171
0
    }
172
0
    memory_free(
173
0
     internal_tree );
174
0
  }
175
0
  return( -1 );
176
5.40k
}
177
178
/* Frees a tree, its sub nodes
179
 * Uses the value_free_function to free the value
180
 * Returns 1 if successful or -1 on error
181
 */
182
int libcdata_btree_free(
183
     libcdata_btree_t **tree,
184
     int (*value_free_function)(
185
            intptr_t **value,
186
            libcerror_error_t **error ),
187
     libcerror_error_t **error )
188
5.40k
{
189
5.40k
  libcdata_internal_btree_t *internal_tree = NULL;
190
5.40k
  static char *function                    = "libcdata_btree_free";
191
5.40k
  int result                               = 1;
192
193
5.40k
  if( tree == NULL )
194
0
  {
195
0
    libcerror_error_set(
196
0
     error,
197
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
198
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
199
0
     "%s: invalid tree.",
200
0
     function );
201
202
0
    return( -1 );
203
0
  }
204
5.40k
  if( *tree != NULL )
205
5.40k
  {
206
5.40k
    internal_tree = (libcdata_internal_btree_t *) *tree;
207
5.40k
    *tree         = NULL;
208
209
#if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBCDATA )
210
    if( libcthreads_read_write_lock_free(
211
         &( internal_tree->read_write_lock ),
212
         error ) != 1 )
213
    {
214
      libcerror_error_set(
215
       error,
216
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
217
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
218
       "%s: unable to free read/write lock.",
219
       function );
220
221
      result = -1;
222
    }
223
#endif
224
5.40k
    if( libcdata_tree_node_free(
225
5.40k
         &( internal_tree->root_node ),
226
5.40k
         (int (*)(intptr_t **, libcerror_error_t **)) &libcdata_btree_values_list_free,
227
5.40k
         error ) != 1 )
228
0
    {
229
0
      libcerror_error_set(
230
0
       error,
231
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
232
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
233
0
       "%s: unable to free root node.",
234
0
       function );
235
236
0
      result = -1;
237
0
    }
238
5.40k
    if( libcdata_array_free(
239
5.40k
         &( internal_tree->values_array ),
240
5.40k
         value_free_function,
241
5.40k
         error ) != 1 )
242
0
    {
243
0
      libcerror_error_set(
244
0
       error,
245
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
246
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
247
0
       "%s: unable to free values array.",
248
0
       function );
249
250
0
      result = -1;
251
0
    }
252
5.40k
    memory_free(
253
5.40k
     internal_tree );
254
5.40k
  }
255
5.40k
  return( result );
256
5.40k
}
257
258
/* TODO add clone function ? */
259
260
/* Retrieves the number of values in the tree
261
 * Returns 1 if successful or -1 on error
262
 */
263
int libcdata_btree_get_number_of_values(
264
     libcdata_btree_t *tree,
265
     int *number_of_values,
266
     libcerror_error_t **error )
267
0
{
268
0
  libcdata_internal_btree_t *internal_tree = NULL;
269
0
  static char *function                    = "libcdata_btree_get_number_of_values";
270
271
0
  if( tree == NULL )
272
0
  {
273
0
    libcerror_error_set(
274
0
     error,
275
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
276
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
277
0
     "%s: invalid tree.",
278
0
     function );
279
280
0
    return( -1 );
281
0
  }
282
0
  internal_tree = (libcdata_internal_btree_t *) tree;
283
284
0
  if( libcdata_array_get_number_of_entries(
285
0
       internal_tree->values_array,
286
0
       number_of_values,
287
0
       error ) != 1 )
288
0
  {
289
0
    libcerror_error_set(
290
0
     error,
291
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
292
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
293
0
     "%s: unable to retrieve number of values array entries.",
294
0
     function );
295
296
0
    return( -1 );
297
0
  }
298
0
  return( 1 );
299
0
}
300
301
/* Retrieves a specific value
302
 * Returns 1 if successful or -1 on error
303
 */
304
int libcdata_btree_get_value_by_index(
305
     libcdata_btree_t *tree,
306
     int value_index,
307
     intptr_t **value,
308
     libcerror_error_t **error )
309
0
{
310
0
  libcdata_internal_btree_t *internal_tree = NULL;
311
0
  static char *function                    = "libcdata_btree_get_value_by_index";
312
313
0
  if( tree == NULL )
314
0
  {
315
0
    libcerror_error_set(
316
0
     error,
317
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
318
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
319
0
     "%s: invalid tree.",
320
0
     function );
321
322
0
    return( -1 );
323
0
  }
324
0
  internal_tree = (libcdata_internal_btree_t *) tree;
325
326
0
  if( libcdata_array_get_entry_by_index(
327
0
       internal_tree->values_array,
328
0
       value_index,
329
0
       value,
330
0
       error ) != 1 )
331
0
  {
332
0
    libcerror_error_set(
333
0
     error,
334
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
335
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
336
0
     "%s: unable to retrieve value: %d from array.",
337
0
     function,
338
0
     value_index );
339
340
0
    return( -1 );
341
0
  }
342
0
  return( 1 );
343
0
}
344
345
/* Retrieves a value from the tree
346
 *
347
 * Uses the value_compare_function to determine the similarity of the entries
348
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
349
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
350
 *
351
 * Returns 1 if successful, 0 if no such value or -1 on error
352
 */
353
int libcdata_btree_get_value_by_value(
354
     libcdata_btree_t *tree,
355
     intptr_t *value,
356
     int (*value_compare_function)(
357
            intptr_t *first_value,
358
            intptr_t *second_value,
359
            libcerror_error_t **error ),
360
     libcdata_tree_node_t **upper_node,
361
     intptr_t **existing_value,
362
     libcerror_error_t **error )
363
0
{
364
0
  libcdata_internal_btree_t *internal_tree       = NULL;
365
0
  libcdata_list_element_t *existing_list_element = NULL;
366
0
  static char *function                          = "libcdata_btree_get_value_by_value";
367
0
  int result                                     = 0;
368
369
0
  if( tree == NULL )
370
0
  {
371
0
    libcerror_error_set(
372
0
     error,
373
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
374
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
375
0
     "%s: invalid tree.",
376
0
     function );
377
378
0
    return( -1 );
379
0
  }
380
0
  internal_tree = (libcdata_internal_btree_t *) tree;
381
382
0
  result = libcdata_btree_node_get_upper_node_by_value(
383
0
            internal_tree->root_node,
384
0
            value,
385
0
            value_compare_function,
386
0
            upper_node,
387
0
            &existing_list_element,
388
0
            error );
389
390
0
  if( result == -1 )
391
0
  {
392
0
    libcerror_error_set(
393
0
     error,
394
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
395
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
396
0
     "%s: unable to retrieve upper node by value.",
397
0
     function );
398
399
0
    return( -1 );
400
0
  }
401
0
  else if( result != 0 )
402
0
  {
403
0
    if( libcdata_list_element_get_value(
404
0
         existing_list_element,
405
0
         existing_value,
406
0
         error ) != 1 )
407
0
    {
408
0
      libcerror_error_set(
409
0
       error,
410
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
411
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
412
0
       "%s: unable to retrieve value from values list element.",
413
0
       function );
414
415
0
      return( -1 );
416
0
    }
417
0
  }
418
0
  else
419
0
  {
420
0
    if( existing_value == NULL )
421
0
    {
422
0
      libcerror_error_set(
423
0
       error,
424
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
425
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
426
0
       "%s: invalid existing value.",
427
0
       function );
428
429
0
      return( -1 );
430
0
    }
431
0
    *existing_value = NULL;
432
0
  }
433
0
  return( result );
434
0
}
435
436
/* Inserts a value into a tree
437
 *
438
 * Uses the value_compare_function to determine the order of the entries
439
 * The value_compare_function should return LIBCDATA_COMPARE_LESS,
440
 * LIBCDATA_COMPARE_EQUAL, LIBCDATA_COMPARE_GREATER if successful or -1 on error
441
 *
442
 * Returns 1 if successful, 0 if the value already exists or -1 on error
443
 */
444
int libcdata_btree_insert_value(
445
     libcdata_btree_t *tree,
446
     int *value_index,
447
     intptr_t *value,
448
     int (*value_compare_function)(
449
            intptr_t *first_value,
450
            intptr_t *second_value,
451
            libcerror_error_t **error ),
452
     libcdata_tree_node_t **upper_node,
453
     intptr_t **existing_value,
454
     libcerror_error_t **error )
455
0
{
456
0
  libcdata_internal_btree_t *internal_tree       = NULL;
457
0
  libcdata_list_t *values_list                   = NULL;
458
0
  libcdata_list_element_t *existing_list_element = NULL;
459
0
  static char *function                          = "libcdata_btree_insert_value";
460
0
  int number_of_values_list_elements             = 0;
461
0
  int result                                     = 0;
462
463
0
  if( tree == NULL )
464
0
  {
465
0
    libcerror_error_set(
466
0
     error,
467
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
468
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
469
0
     "%s: invalid tree.",
470
0
     function );
471
472
0
    return( -1 );
473
0
  }
474
0
  internal_tree = (libcdata_internal_btree_t *) tree;
475
476
0
  if( upper_node == NULL )
477
0
  {
478
0
    libcerror_error_set(
479
0
     error,
480
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
481
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
482
0
     "%s: invalid upper node.",
483
0
     function );
484
485
0
    return( -1 );
486
0
  }
487
0
  if( value_index == NULL )
488
0
  {
489
0
    libcerror_error_set(
490
0
     error,
491
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
492
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
493
0
     "%s: invalid value index.",
494
0
     function );
495
496
0
    return( -1 );
497
0
  }
498
0
  if( existing_value == NULL )
499
0
  {
500
0
    libcerror_error_set(
501
0
     error,
502
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
503
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
504
0
     "%s: invalid existing value.",
505
0
     function );
506
507
0
    return( -1 );
508
0
  }
509
0
  result = libcdata_btree_node_get_upper_node_by_value(
510
0
            internal_tree->root_node,
511
0
            value,
512
0
            value_compare_function,
513
0
            upper_node,
514
0
            &existing_list_element,
515
0
            error );
516
517
0
  if( result == -1 )
518
0
  {
519
0
    libcerror_error_set(
520
0
     error,
521
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
522
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
523
0
     "%s: unable to retrieve upper node in root node.",
524
0
     function );
525
526
0
    return( -1 );
527
0
  }
528
0
  else if( result != 0 )
529
0
  {
530
0
    if( libcdata_list_element_get_value(
531
0
         existing_list_element,
532
0
         existing_value,
533
0
         error ) != 1 )
534
0
    {
535
0
      libcerror_error_set(
536
0
       error,
537
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
538
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
539
0
       "%s: unable to retrieve value from values list element.",
540
0
       function );
541
542
0
      return( -1 );
543
0
    }
544
0
    return( 0 );
545
0
  }
546
0
  *existing_value = NULL;
547
548
0
  if( libcdata_btree_node_insert_value(
549
0
       *upper_node,
550
0
       value,
551
0
       value_compare_function,
552
0
       error ) != 1 )
553
0
  {
554
0
    libcerror_error_set(
555
0
     error,
556
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
557
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
558
0
     "%s: unable to insert value in upper node.",
559
0
     function );
560
561
0
    return( -1 );
562
0
  }
563
0
  if( libcdata_tree_node_get_value(
564
0
       *upper_node,
565
0
       (intptr_t **) &values_list,
566
0
       error ) != 1 )
567
0
  {
568
0
    libcerror_error_set(
569
0
     error,
570
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
571
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
572
0
     "%s: unable to retrieve values list.",
573
0
     function );
574
575
0
    return( -1 );
576
0
  }
577
0
  if( libcdata_list_get_number_of_elements(
578
0
       values_list,
579
0
       &number_of_values_list_elements,
580
0
       error ) != 1 )
581
0
  {
582
0
    libcerror_error_set(
583
0
     error,
584
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
585
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
586
0
     "%s: unable to retrieve number of values list elements.",
587
0
     function );
588
589
0
    return( -1 );
590
0
  }
591
0
  if( number_of_values_list_elements >= internal_tree->maximum_number_of_values )
592
0
  {
593
0
    if( libcdata_btree_node_split(
594
0
         *upper_node,
595
0
         error ) != 1 )
596
0
    {
597
0
      libcerror_error_set(
598
0
       error,
599
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
600
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
601
0
       "%s: unable to split upper node.",
602
0
       function );
603
604
0
      return( -1 );
605
0
    }
606
/* TODO do merge of upper node with its parent node */
607
/* TODO loop until number_of_values_list_elements < internal_tree->maximum_number_of_values */
608
609
    /* Make sure existing list element updated after the split
610
     */
611
0
    result = libcdata_btree_node_get_sub_node_by_value(
612
0
              *upper_node,
613
0
              value,
614
0
              value_compare_function,
615
0
              upper_node,
616
0
              &existing_list_element,
617
0
              error );
618
619
0
    if( result == -1 )
620
0
    {
621
0
      libcerror_error_set(
622
0
       error,
623
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
624
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
625
0
       "%s: unable to retrieve split sub node by value.",
626
0
       function );
627
628
0
      return( -1 );
629
0
    }
630
0
    result = libcdata_btree_node_get_sub_node_by_value(
631
0
              *upper_node,
632
0
              value,
633
0
              value_compare_function,
634
0
              upper_node,
635
0
              &existing_list_element,
636
0
              error );
637
638
0
    if( result != 1 )
639
0
    {
640
0
      libcerror_error_set(
641
0
       error,
642
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
643
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
644
0
       "%s: unable to retrieve split sub node by value.",
645
0
       function );
646
647
0
      return( -1 );
648
0
    }
649
0
  }
650
0
  if( libcdata_array_append_entry(
651
0
       internal_tree->values_array,
652
0
       value_index,
653
0
       value,
654
0
       error ) != 1 )
655
0
  {
656
0
    libcerror_error_set(
657
0
     error,
658
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
659
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
660
0
     "%s: unable to append value to values array.",
661
0
     function );
662
663
0
    return( -1 );
664
0
  }
665
0
  return( 1 );
666
0
}
667
668
/* Replaces a value in the tree
669
 * Returns 1 if successful or -1 on error
670
 */
671
int libcdata_btree_replace_value(
672
     libcdata_btree_t *tree,
673
     libcdata_tree_node_t *upper_node,
674
     int *value_index,
675
     intptr_t *value,
676
     int *replacement_value_index,
677
     intptr_t *replacement_value,
678
     libcerror_error_t **error )
679
0
{
680
0
  libcdata_internal_btree_t *internal_tree = NULL;
681
0
  intptr_t *check_value                    = NULL;
682
0
  static char *function                    = "libcdata_btree_replace_value";
683
0
  int number_of_sub_nodes                  = 0;
684
685
0
  if( tree == NULL )
686
0
  {
687
0
    libcerror_error_set(
688
0
     error,
689
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
690
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
691
0
     "%s: invalid tree.",
692
0
     function );
693
694
0
    return( -1 );
695
0
  }
696
0
  internal_tree = (libcdata_internal_btree_t *) tree;
697
698
0
  if( upper_node == NULL )
699
0
  {
700
0
    libcerror_error_set(
701
0
     error,
702
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
703
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
704
0
     "%s: invalid upper node.",
705
0
     function );
706
707
0
    return( -1 );
708
0
  }
709
0
  if( value_index == NULL )
710
0
  {
711
0
    libcerror_error_set(
712
0
     error,
713
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
714
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
715
0
     "%s: invalid value index.",
716
0
     function );
717
718
0
    return( -1 );
719
0
  }
720
0
  if( replacement_value_index == NULL )
721
0
  {
722
0
    libcerror_error_set(
723
0
     error,
724
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
725
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
726
0
     "%s: invalid value index.",
727
0
     function );
728
729
0
    return( -1 );
730
0
  }
731
0
  if( libcdata_tree_node_get_number_of_sub_nodes(
732
0
       upper_node,
733
0
       &number_of_sub_nodes,
734
0
       error ) != 1 )
735
0
  {
736
0
    libcerror_error_set(
737
0
     error,
738
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
739
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
740
0
     "%s: unable to retrieve number of sub nodes.",
741
0
     function );
742
743
0
    return( -1 );
744
0
  }
745
0
  if( number_of_sub_nodes != 0 )
746
0
  {
747
0
    libcerror_error_set(
748
0
     error,
749
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
750
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
751
0
     "%s: cannot replace upper node with sub nodes.",
752
0
     function );
753
754
0
    return( -1 );
755
0
  }
756
0
  if( libcdata_array_get_entry_by_index(
757
0
       internal_tree->values_array,
758
0
       *value_index,
759
0
       &check_value,
760
0
       error ) != 1 )
761
0
  {
762
0
    libcerror_error_set(
763
0
     error,
764
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
765
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
766
0
     "%s: unable to retrieve value: %d from array.",
767
0
     function,
768
0
     *value_index );
769
770
0
    return( -1 );
771
0
  }
772
0
  if( value != check_value )
773
0
  {
774
0
    libcerror_error_set(
775
0
     error,
776
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
777
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
778
0
     "%s: invalid value: %d value out of bounds.",
779
0
     function,
780
0
     *value_index );
781
782
0
    return( -1 );
783
0
  }
784
0
  if( libcdata_btree_node_replace_value(
785
0
       upper_node,
786
0
       value,
787
0
       replacement_value,
788
0
       error ) != 1 )
789
0
  {
790
0
    libcerror_error_set(
791
0
     error,
792
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
793
0
     LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
794
0
     "%s: unable to replace value: %d.",
795
0
     function,
796
0
     *value_index );
797
798
0
    return( -1 );
799
0
  }
800
0
  if( libcdata_array_set_entry_by_index(
801
0
       internal_tree->values_array,
802
0
       *value_index,
803
0
       replacement_value,
804
0
       error ) != 1 )
805
0
  {
806
0
    libcerror_error_set(
807
0
     error,
808
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
809
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
810
0
     "%s: unable to set value: %d in values array.",
811
0
     function,
812
0
     *value_index );
813
814
0
    return( -1 );
815
0
  }
816
0
  *replacement_value_index = *value_index;
817
0
  *value_index             = -1;
818
819
0
  return( 1 );
820
0
}
821
822
/* Removes a value from the tree
823
 * Returns 1 if successful or -1 on error
824
 */
825
int libcdata_btree_remove_value(
826
     libcdata_btree_t *tree,
827
     libcdata_tree_node_t *upper_node,
828
     int *value_index,
829
     intptr_t *value,
830
     libcerror_error_t **error )
831
0
{
832
0
  libcdata_internal_btree_t *internal_tree = NULL;
833
0
  intptr_t *check_value                    = NULL;
834
0
  static char *function                    = "libcdata_btree_remove_value";
835
0
  int number_of_sub_nodes                  = 0;
836
837
0
  if( tree == NULL )
838
0
  {
839
0
    libcerror_error_set(
840
0
     error,
841
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
842
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
843
0
     "%s: invalid tree.",
844
0
     function );
845
846
0
    return( -1 );
847
0
  }
848
0
  internal_tree = (libcdata_internal_btree_t *) tree;
849
850
0
  if( upper_node == NULL )
851
0
  {
852
0
    libcerror_error_set(
853
0
     error,
854
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
855
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
856
0
     "%s: invalid upper node.",
857
0
     function );
858
859
0
    return( -1 );
860
0
  }
861
0
  if( value_index == NULL )
862
0
  {
863
0
    libcerror_error_set(
864
0
     error,
865
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
866
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
867
0
     "%s: invalid value index.",
868
0
     function );
869
870
0
    return( -1 );
871
0
  }
872
0
  if( libcdata_tree_node_get_number_of_sub_nodes(
873
0
       upper_node,
874
0
       &number_of_sub_nodes,
875
0
       error ) != 1 )
876
0
  {
877
0
    libcerror_error_set(
878
0
     error,
879
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
880
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
881
0
     "%s: unable to retrieve number of sub nodes.",
882
0
     function );
883
884
0
    return( -1 );
885
0
  }
886
0
  if( number_of_sub_nodes != 0 )
887
0
  {
888
0
    libcerror_error_set(
889
0
     error,
890
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
891
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
892
0
     "%s: cannot replace upper node with sub nodes.",
893
0
     function );
894
895
0
    return( -1 );
896
0
  }
897
0
  if( libcdata_array_get_entry_by_index(
898
0
       internal_tree->values_array,
899
0
       *value_index,
900
0
       &check_value,
901
0
       error ) != 1 )
902
0
  {
903
0
    libcerror_error_set(
904
0
     error,
905
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
906
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
907
0
     "%s: unable to retrieve value: %d from array.",
908
0
     function,
909
0
     *value_index );
910
911
0
    return( -1 );
912
0
  }
913
0
  if( value != check_value )
914
0
  {
915
0
    libcerror_error_set(
916
0
     error,
917
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
918
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
919
0
     "%s: invalid value: %d value out of bounds.",
920
0
     function,
921
0
     *value_index );
922
923
0
    return( -1 );
924
0
  }
925
0
  if( libcdata_btree_node_remove_value(
926
0
       upper_node,
927
0
       value,
928
0
       NULL,
929
0
       error ) != 1 )
930
0
  {
931
0
    libcerror_error_set(
932
0
     error,
933
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
934
0
     LIBCERROR_RUNTIME_ERROR_REMOVE_FAILED,
935
0
     "%s: unable to remove value: %d from upper node.",
936
0
     function,
937
0
     *value_index );
938
939
0
    return( -1 );
940
0
  }
941
/* TODO reshuffle values array ?
942
 * Better to mark and ignore deleted items, otherwise index values need to be updated as well
943
 */
944
0
  if( libcdata_array_set_entry_by_index(
945
0
       internal_tree->values_array,
946
0
       *value_index,
947
0
       NULL,
948
0
       error ) != 1 )
949
0
  {
950
0
    libcerror_error_set(
951
0
     error,
952
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
953
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
954
0
     "%s: unable to set value: %d in values array.",
955
0
     function,
956
0
     *value_index );
957
958
0
    return( -1 );
959
0
  }
960
0
  *value_index = -1;
961
962
0
  return( 1 );
963
0
}
964