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_id_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_init( utf8stringbuf_get_size(out_name)-RESERVED_FOR_NUMBER, utf8stringbuf_get_string(out_name) ); 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-2024 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 : */