strtonum.c (2072B)
1 /* This program is licensed under the terms of GNU GPL v3 or (at your option) 2 * any later version. Copyright (C) 2026 Страхиња Радић. 3 * See the file LICENSE for exact copyright and license details. */ 4 5 #include <errno.h> 6 #include <limits.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 #include "strtonum.h" 12 13 /* Returns 0 on no error, otherwise returns 1 after outputting error message */ 14 int 15 stn_handle_error(const char* str, const long long minval, 16 const long long maxval, const int errornum) 17 { 18 switch (errornum) 19 { 20 case STN_NOTNUM: 21 fprintf(stderr, "strtonumber: Not a number: %s\n", str); 22 return 1; 23 case STN_INVLIMITS: 24 fprintf(stderr, "strtonumber: Invalid limit specification\n"); 25 return 1; 26 case STN_UNDERFLOW: 27 fprintf(stderr, "strtonumber: Underflow: %s < %lld\n", str, 28 minval); 29 return 1; 30 case STN_OVERFLOW: 31 fprintf(stderr, "strtonumber: Overflow: %s > %lld\n", str, 32 maxval); 33 return 1; 34 default:; 35 } 36 return 0; 37 } 38 39 /* - Returns the converted number or 0 on error (*not* indicative of error; see 40 * below) 41 * - Clears errno (discards any previous value) because of strtoll 42 * - Instead, returns any errors in errornum (if non-NULL); 43 * *errornum == STN_NONE indicates success, any other value indicates error */ 44 long long 45 strtonumber(const char* str, const long long minval, const long long maxval, 46 int* errornum) 47 { 48 long long n; 49 char* end = NULL; 50 51 if (minval > maxval) 52 { 53 if (errornum) 54 *errornum = STN_INVLIMITS; 55 return 0; 56 } 57 errno = 0; 58 if (errornum) 59 *errornum = STN_NONE; 60 n = strtoll(str, &end, 10); 61 if (!*str || *end) 62 { 63 errno = 0; 64 if (errornum) 65 *errornum = STN_NOTNUM; 66 return 0; 67 } 68 else if (errno == ERANGE) 69 { 70 errno = 0; 71 if (errornum) 72 *errornum 73 = n == LLONG_MIN ? STN_UNDERFLOW : STN_OVERFLOW; 74 return 0; 75 } 76 else 77 { 78 errno = 0; 79 if (n > maxval) 80 { 81 if (errornum) 82 *errornum = STN_OVERFLOW; 83 return 0; 84 } 85 else if (n < minval) 86 { 87 if (errornum) 88 *errornum = STN_UNDERFLOW; 89 return 0; 90 } 91 else 92 return n; 93 } 94 /* Not reached */ 95 return n; 96 }