Branch data Line data Source code
1 : : // Copyright 2019-2026 David Robillard <d@drobilla.net> 2 : : // SPDX-License-Identifier: ISC 3 : : 4 : : #include "year.h" 5 : : #include "int_math.h" 6 : : #include "number_utils.h" 7 : : #include "result.h" 8 : : #include "write_utils.h" 9 : : 10 : : #include <exess/exess.h> 11 : : 12 : : #include <stdbool.h> 13 : : #include <stdint.h> 14 : : #include <stdlib.h> 15 : : 16 : : EXESS_NONBLOCKING ExessResult 17 : 354 : read_year_number(int16_t* const out, const char* const str) 18 : : { 19 : 354 : *out = 0; 20 : : 21 : : // Read leading sign if present 22 : 354 : size_t i = 0; 23 : 354 : int sign = 1; 24 [ + + ]: 354 : if (str[i] == '-') { 25 : 16 : sign = -1; 26 : 16 : ++i; 27 : : } 28 : : 29 : : // Read digits 30 : 354 : uint64_t magnitude = 0; 31 : 354 : const ExessResult r = read_digits(&magnitude, str + i); 32 : : 33 : 354 : i += r.count; 34 [ + + ]: 354 : if (r.status) { 35 : 6 : return RESULT(r.status, i + r.count); 36 : : } 37 : : 38 [ + + ]: 348 : if (sign > 0) { 39 [ + + ]: 332 : if (magnitude > (uint16_t)INT16_MAX) { 40 : 1 : return RESULT(EXESS_OUT_OF_RANGE, i); 41 : : } 42 : : 43 : 331 : *out = (int16_t)magnitude; 44 : : } else { 45 : 16 : const uint16_t min_magnitude = (uint16_t)(-(INT16_MIN + 1)) + 1; 46 [ + + ]: 16 : if (magnitude > min_magnitude) { 47 : 1 : return RESULT(EXESS_OUT_OF_RANGE, i); 48 : : } 49 : : 50 [ + + ]: 15 : if (magnitude == min_magnitude) { 51 : 3 : *out = INT16_MIN; 52 : : } else { 53 : 12 : *out = (int16_t)(-(int16_t)magnitude); 54 : : } 55 : : } 56 : : 57 [ + + ]: 346 : return RESULT(r.count >= 4 ? EXESS_SUCCESS : EXESS_EXPECTED_DIGIT, i); 58 : : } 59 : : 60 : : EXESS_NONBLOCKING ExessResult 61 : 147 : write_year_number(const int16_t value, const size_t buf_size, char* const buf) 62 : : { 63 : 147 : const uint32_t abs_year = (uint32_t)abs(value); 64 : 147 : const uint8_t n_digits = exess_num_digits(abs_year); 65 : 147 : const bool is_negative = value < 0; 66 : : 67 : : // Write sign 68 : 147 : size_t i = 0; 69 [ + + ]: 147 : if (is_negative) { 70 : 20 : i += write_char('-', buf_size, buf, i); 71 : : } 72 : : 73 : : // Write leading zeros to ensure we have at least 4 year digits 74 [ + + ]: 180 : for (size_t j = n_digits; j < 4; ++j) { 75 : 33 : i += write_char('0', buf_size, buf, i); 76 : : } 77 : : 78 : 147 : const ExessResult yr = write_digits(abs_year, buf_size, buf, i); 79 : 147 : return end_write(yr.status, buf_size, buf, i + yr.count); 80 : : }