1*4afad4b7Schristos /* $NetBSD: parseint.c,v 1.1 2024/02/18 20:57:49 christos Exp $ */
2*4afad4b7Schristos
3*4afad4b7Schristos /*
4*4afad4b7Schristos * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5*4afad4b7Schristos *
6*4afad4b7Schristos * SPDX-License-Identifier: MPL-2.0
7*4afad4b7Schristos *
8*4afad4b7Schristos * This Source Code Form is subject to the terms of the Mozilla Public
9*4afad4b7Schristos * License, v. 2.0. If a copy of the MPL was not distributed with this
10*4afad4b7Schristos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11*4afad4b7Schristos *
12*4afad4b7Schristos * See the COPYRIGHT file distributed with this work for additional
13*4afad4b7Schristos * information regarding copyright ownership.
14*4afad4b7Schristos */
15*4afad4b7Schristos
16*4afad4b7Schristos /*! \file */
17*4afad4b7Schristos
18*4afad4b7Schristos #include <ctype.h>
19*4afad4b7Schristos #include <errno.h>
20*4afad4b7Schristos #include <inttypes.h>
21*4afad4b7Schristos #include <limits.h>
22*4afad4b7Schristos #include <stdlib.h>
23*4afad4b7Schristos
24*4afad4b7Schristos #include <isc/parseint.h>
25*4afad4b7Schristos #include <isc/result.h>
26*4afad4b7Schristos
27*4afad4b7Schristos isc_result_t
isc_parse_uint32(uint32_t * uip,const char * string,int base)28*4afad4b7Schristos isc_parse_uint32(uint32_t *uip, const char *string, int base) {
29*4afad4b7Schristos unsigned long n;
30*4afad4b7Schristos uint32_t r;
31*4afad4b7Schristos char *e;
32*4afad4b7Schristos if (!isalnum((unsigned char)(string[0]))) {
33*4afad4b7Schristos return (ISC_R_BADNUMBER);
34*4afad4b7Schristos }
35*4afad4b7Schristos errno = 0;
36*4afad4b7Schristos n = strtoul(string, &e, base);
37*4afad4b7Schristos if (*e != '\0') {
38*4afad4b7Schristos return (ISC_R_BADNUMBER);
39*4afad4b7Schristos }
40*4afad4b7Schristos /*
41*4afad4b7Schristos * Where long is 64 bits we need to convert to 32 bits then test for
42*4afad4b7Schristos * equality. This is a no-op on 32 bit machines and a good compiler
43*4afad4b7Schristos * will optimise it away.
44*4afad4b7Schristos */
45*4afad4b7Schristos r = (uint32_t)n;
46*4afad4b7Schristos if ((n == ULONG_MAX && errno == ERANGE) || (n != (unsigned long)r)) {
47*4afad4b7Schristos return (ISC_R_RANGE);
48*4afad4b7Schristos }
49*4afad4b7Schristos *uip = r;
50*4afad4b7Schristos return (ISC_R_SUCCESS);
51*4afad4b7Schristos }
52*4afad4b7Schristos
53*4afad4b7Schristos isc_result_t
isc_parse_uint16(uint16_t * uip,const char * string,int base)54*4afad4b7Schristos isc_parse_uint16(uint16_t *uip, const char *string, int base) {
55*4afad4b7Schristos uint32_t val;
56*4afad4b7Schristos isc_result_t result;
57*4afad4b7Schristos result = isc_parse_uint32(&val, string, base);
58*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
59*4afad4b7Schristos return (result);
60*4afad4b7Schristos }
61*4afad4b7Schristos if (val > 0xFFFF) {
62*4afad4b7Schristos return (ISC_R_RANGE);
63*4afad4b7Schristos }
64*4afad4b7Schristos *uip = (uint16_t)val;
65*4afad4b7Schristos return (ISC_R_SUCCESS);
66*4afad4b7Schristos }
67*4afad4b7Schristos
68*4afad4b7Schristos isc_result_t
isc_parse_uint8(uint8_t * uip,const char * string,int base)69*4afad4b7Schristos isc_parse_uint8(uint8_t *uip, const char *string, int base) {
70*4afad4b7Schristos uint32_t val;
71*4afad4b7Schristos isc_result_t result;
72*4afad4b7Schristos result = isc_parse_uint32(&val, string, base);
73*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
74*4afad4b7Schristos return (result);
75*4afad4b7Schristos }
76*4afad4b7Schristos if (val > 0xFF) {
77*4afad4b7Schristos return (ISC_R_RANGE);
78*4afad4b7Schristos }
79*4afad4b7Schristos *uip = (uint8_t)val;
80*4afad4b7Schristos return (ISC_R_SUCCESS);
81*4afad4b7Schristos }
82