Line data Source code
1 : /* File: ctrl_simple_changer.c; Copyright and License: see below */
2 :
3 : #include "ctrl_simple_changer.h"
4 : #include "u8/u8_trace.h"
5 : #include "u8/u8_log.h"
6 : #include <assert.h>
7 :
8 0 : static inline void ctrl_simple_changer_init ( ctrl_simple_changer_t *this_,
9 : ctrl_controller_t *controller,
10 : data_database_reader_t *db_reader )
11 : {
12 0 : U8_TRACE_BEGIN();
13 0 : assert( NULL != controller );
14 0 : assert( NULL != db_reader );
15 :
16 : /* init member attributes */
17 0 : (*this_).controller = controller;
18 0 : (*this_).db_reader = db_reader;
19 :
20 0 : U8_TRACE_END();
21 0 : }
22 :
23 0 : static inline void ctrl_simple_changer_destroy ( ctrl_simple_changer_t *this_ )
24 : {
25 0 : U8_TRACE_BEGIN();
26 0 : assert( NULL != (*this_).controller );
27 0 : assert( NULL != (*this_).db_reader );
28 :
29 : /* destroy member attributes */
30 0 : (*this_).controller = NULL;
31 0 : (*this_).db_reader = NULL;
32 :
33 0 : U8_TRACE_END();
34 0 : }
35 :
36 0 : static inline u8_error_t ctrl_simple_changer_update_classifier_name ( ctrl_simple_changer_t *this_,
37 : data_row_t classifier_id,
38 : const char* new_classifier_name,
39 : u8_error_t* out_info )
40 : {
41 0 : U8_TRACE_BEGIN();
42 0 : assert( NULL != new_classifier_name );
43 0 : assert( NULL != out_info );
44 0 : u8_error_t result = U8_ERROR_NONE;
45 :
46 0 : ctrl_classifier_controller_t *const classifier_ctrl = ctrl_controller_get_classifier_control_ptr( (*this_).controller);
47 :
48 : /* To not run into TOCTOU problems, we try to change the name immediately and then check for success afterwards: */
49 : const u8_error_t initial_err
50 0 : = ctrl_classifier_controller_update_classifier_name( classifier_ctrl,
51 : classifier_id,
52 : new_classifier_name
53 : );
54 0 : if ( u8_error_contains( initial_err, U8_ERROR_DUPLICATE_NAME ) )
55 : {
56 0 : *out_info = initial_err;
57 :
58 : /* find an alternative, unused name */
59 : char wish_name_buf[DATA_CLASSIFIER_MAX_NAME_SIZE];
60 0 : utf8stringbuf_t wish_name = UTF8STRINGBUF( wish_name_buf );
61 0 : result |= utf8stringbuf_copy_str( &wish_name, new_classifier_name ); /* error to be reported to caller */
62 : {
63 0 : bool name_ok = false;
64 : static const uint_fast16_t MAX_SEARCH_STEP = 10000;
65 : static const uint_fast16_t FIRST_STEP = 2;
66 0 : for ( uint_fast16_t search_step = FIRST_STEP; ( search_step < MAX_SEARCH_STEP )&&( ! name_ok )&&( result == U8_ERROR_NONE ); search_step ++ )
67 : {
68 : char new_name_buf[DATA_CLASSIFIER_MAX_NAME_SIZE];
69 0 : utf8stringbuf_t new_name = UTF8STRINGBUF( new_name_buf );
70 : const u8_error_t trunc_err
71 0 : = ctrl_simple_changer_private_propose_classifier_name( this_,
72 0 : utf8stringbuf_get_string( &wish_name ),
73 : search_step,
74 : new_name
75 : );
76 0 : if ( trunc_err != U8_ERROR_NONE )
77 : {
78 0 : U8_TRACE_INFO_STR("Name truncated at search for alternative:", utf8stringbuf_get_string( &new_name ) );
79 : }
80 : const u8_error_t retry_err
81 0 : = ctrl_classifier_controller_update_classifier_name( classifier_ctrl,
82 : classifier_id,
83 0 : utf8stringbuf_get_string( &new_name )
84 : );
85 0 : if ( u8_error_contains( retry_err, U8_ERROR_DUPLICATE_NAME ) )
86 : {
87 0 : *out_info |= retry_err;
88 : }
89 : else
90 : {
91 0 : name_ok = ( retry_err == U8_ERROR_NONE );
92 0 : result |= retry_err;
93 : }
94 : }
95 : }
96 : }
97 : else
98 : {
99 0 : result = initial_err;
100 0 : *out_info = U8_ERROR_NONE;
101 : }
102 :
103 0 : U8_TRACE_END_ERR( result );
104 0 : return result;
105 : }
106 :
107 0 : static inline u8_error_t ctrl_simple_changer_private_propose_classifier_name ( ctrl_simple_changer_t *this_,
108 : const char* base_classifier_name,
109 : uint_fast16_t iteration,
110 : utf8stringbuf_t out_name )
111 : {
112 0 : U8_TRACE_BEGIN();
113 0 : const size_t RESERVED_FOR_NUMBER = 5;
114 0 : assert( NULL != base_classifier_name );
115 0 : assert( utf8stringbuf_get_size( &out_name ) > RESERVED_FOR_NUMBER );
116 0 : u8_error_t result = U8_ERROR_NONE;
117 :
118 : /* find an alternative, unused name */
119 : /* copy the base_classifier_name to newname_buf */
120 : {
121 : utf8stringbuf_t shortened_new_name
122 0 : = utf8stringbuf_new( utf8stringbuf_get_string( &out_name ), utf8stringbuf_get_size( &out_name ) - RESERVED_FOR_NUMBER );
123 0 : result |= utf8stringbuf_copy_str( &shortened_new_name, base_classifier_name );
124 : /* null termination is guaranteed, also this function does not cut an utf8 code point in the middle. */
125 : }
126 : /* append a separator and the iteration number */
127 0 : result |= utf8stringbuf_append_str( &out_name, "-" );
128 0 : result |= utf8stringbuf_append_int( &out_name, iteration );
129 :
130 0 : U8_TRACE_END_ERR( result );
131 0 : return result;
132 : }
133 :
134 :
135 : /*
136 : Copyright 2023-2025 Andreas Warnke
137 :
138 : Licensed under the Apache License, Version 2.0 (the "License");
139 : you may not use this file except in compliance with the License.
140 : You may obtain a copy of the License at
141 :
142 : http://www.apache.org/licenses/LICENSE-2.0
143 :
144 : Unless required by applicable law or agreed to in writing, software
145 : distributed under the License is distributed on an "AS IS" BASIS,
146 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
147 : See the License for the specific language governing permissions and
148 : limitations under the License.
149 : */
|