| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * $Id$ | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-02-20 15:35:16 +00:00
										 |  |  |     Copyright (c) 2016-2020 Chung, Hyung-Hwan. All rights reserved. | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |     modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |     are met: | 
					
						
							|  |  |  |     1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |     2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |        documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | 
					
						
							|  |  |  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
					
						
							|  |  |  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
					
						
							|  |  |  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
					
						
							|  |  |  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
					
						
							|  |  |  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
					
						
							|  |  |  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
					
						
							|  |  |  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							|  |  |  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
					
						
							|  |  |  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int fmt_uintmax ( | 
					
						
							|  |  |  | 	char_t* buf, int size,  | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	hio_uintmax_t value, int base_and_flags, int prec, | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 	char_t fillchar, char_t signchar, const char_t* prefix) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	char_t tmp[(HIO_SIZEOF(hio_uintmax_t) * 8)]; | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 	int reslen, base, fillsize, reqlen, pflen, preczero; | 
					
						
							|  |  |  | 	char_t* p, * bp, * be; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	const hio_bch_t* xbasestr; | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	base = base_and_flags & 0x3F; | 
					
						
							|  |  |  | 	if (base < 2 || base > 36) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	xbasestr = (base_and_flags & HIO_FMT_INTMAX_UPPERCASE)? | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 		"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ": | 
					
						
							|  |  |  | 		"0123456789abcdefghijklmnopqrstuvwxyz"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	if ((base_and_flags & HIO_FMT_INTMAX_NOZERO) && value == 0)  | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		p = tmp;  | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		if (base_and_flags & HIO_FMT_INTMAX_ZEROLEAD)  | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			/* NOZERO emits no digit, ZEROLEAD emits 1 digit.
 | 
					
						
							|  |  |  | 			 * so it emits '0' */ | 
					
						
							|  |  |  | 			reslen = 1; | 
					
						
							|  |  |  | 			preczero = 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* since the value is zero, emit no digits */ | 
					
						
							|  |  |  | 			reslen = 0; | 
					
						
							|  |  |  | 			preczero = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		hio_uintmax_t v = value; | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* store the resulting numeric string into 'tmp' first */ | 
					
						
							|  |  |  | 		p = tmp;  | 
					
						
							|  |  |  | 		do | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*p++ = xbasestr[v % base]; | 
					
						
							|  |  |  | 			v /= base; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		while (v > 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* reslen is the length of the resulting string without padding. */ | 
					
						
							|  |  |  | 		reslen = (int)(p - tmp); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		/* precision specified the minum number of digits to produce.
 | 
					
						
							|  |  |  | 		 * so if the precision is larger that the digits produced,  | 
					
						
							|  |  |  | 		 * reslen should be adjusted to precision */ | 
					
						
							|  |  |  | 		if (prec > reslen)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* if the precision is greater than the actual digits
 | 
					
						
							|  |  |  | 			 * made from the value, 0 is inserted in front. | 
					
						
							|  |  |  | 			 * ZEROLEAD doesn't have to be handled explicitly | 
					
						
							|  |  |  | 			 * since it's achieved effortlessly */ | 
					
						
							|  |  |  | 			preczero = prec - reslen; | 
					
						
							|  |  |  | 			reslen = prec; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			preczero = 0; | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 			if ((base_and_flags & HIO_FMT_INTMAX_ZEROLEAD) && value != 0)  | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				/* if value is zero, 0 is emitted from it. 
 | 
					
						
							|  |  |  | 				 * so ZEROLEAD don't need to add another 0. */ | 
					
						
							|  |  |  | 				preczero++; | 
					
						
							|  |  |  | 				reslen++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (signchar) reslen++; /* increment reslen for the sign character */ | 
					
						
							|  |  |  | 	if (prefix) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* since the length can be truncated for different type sizes,
 | 
					
						
							|  |  |  | 		 * don't pass in a very long prefix. */ | 
					
						
							|  |  |  | 		const char_t* pp; | 
					
						
							|  |  |  | 		for (pp = prefix; *pp != '\0'; pp++) ; | 
					
						
							|  |  |  | 		pflen = pp - prefix; | 
					
						
							|  |  |  | 		reslen += pflen; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else pflen = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* get the required buffer size for lossless formatting */ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	reqlen = (base_and_flags & HIO_FMT_INTMAX_NONULL)? reslen: (reslen + 1); | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (size <= 0 || | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	    ((base_and_flags & HIO_FMT_INTMAX_NOTRUNC) && size < reqlen)) | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		return -reqlen; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* get the size to fill with fill characters */ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	fillsize = (base_and_flags & HIO_FMT_INTMAX_NONULL)? size: (size - 1); | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 	bp = buf; | 
					
						
							|  |  |  | 	be = buf + fillsize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* fill space */ | 
					
						
							|  |  |  | 	if (fillchar != '\0') | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		if (base_and_flags & HIO_FMT_INTMAX_FILLRIGHT) | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			/* emit sign */ | 
					
						
							|  |  |  | 			if (signchar && bp < be) *bp++ = signchar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* copy prefix if necessary */ | 
					
						
							|  |  |  | 			if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* add 0s for precision */ | 
					
						
							|  |  |  | 			while (preczero > 0 && bp < be)  | 
					
						
							|  |  |  | 			{  | 
					
						
							|  |  |  | 				*bp++ = '0'; | 
					
						
							|  |  |  | 				preczero--;  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* copy the numeric string to the destination buffer */ | 
					
						
							|  |  |  | 			while (p > tmp && bp < be) *bp++ = *--p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* fill the right side */ | 
					
						
							|  |  |  | 			while (fillsize > reslen) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				*bp++ = fillchar; | 
					
						
							|  |  |  | 				fillsize--; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 		else if (base_and_flags & HIO_FMT_INTMAX_FILLCENTER) | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			/* emit sign */ | 
					
						
							|  |  |  | 			if (signchar && bp < be) *bp++ = signchar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* fill the left side */ | 
					
						
							|  |  |  | 			while (fillsize > reslen) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				*bp++ = fillchar; | 
					
						
							|  |  |  | 				fillsize--; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* copy prefix if necessary */ | 
					
						
							|  |  |  | 			if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* add 0s for precision */ | 
					
						
							|  |  |  | 			while (preczero > 0 && bp < be)  | 
					
						
							|  |  |  | 			{  | 
					
						
							|  |  |  | 				*bp++ = '0'; | 
					
						
							|  |  |  | 				preczero--;  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* copy the numeric string to the destination buffer */ | 
					
						
							|  |  |  | 			while (p > tmp && bp < be) *bp++ = *--p; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* fill the left side */ | 
					
						
							|  |  |  | 			while (fillsize > reslen) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				*bp++ = fillchar; | 
					
						
							|  |  |  | 				fillsize--; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* emit sign */ | 
					
						
							|  |  |  | 			if (signchar && bp < be) *bp++ = signchar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* copy prefix if necessary */ | 
					
						
							|  |  |  | 			if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* add 0s for precision */ | 
					
						
							|  |  |  | 			while (preczero > 0 && bp < be)  | 
					
						
							|  |  |  | 			{  | 
					
						
							|  |  |  | 				*bp++ = '0'; | 
					
						
							|  |  |  | 				preczero--;  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* copy the numeric string to the destination buffer */ | 
					
						
							|  |  |  | 			while (p > tmp && bp < be) *bp++ = *--p; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* emit sign */ | 
					
						
							|  |  |  | 		if (signchar && bp < be) *bp++ = signchar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* copy prefix if necessary */ | 
					
						
							|  |  |  | 		if (prefix) while (*prefix && bp < be) *bp++ = *prefix++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* add 0s for precision */ | 
					
						
							|  |  |  | 		while (preczero > 0 && bp < be)  | 
					
						
							|  |  |  | 		{  | 
					
						
							|  |  |  | 			*bp++ = '0'; | 
					
						
							|  |  |  | 			preczero--;  | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* copy the numeric string to the destination buffer */ | 
					
						
							|  |  |  | 		while (p > tmp && bp < be) *bp++ = *--p; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 07:30:20 +00:00
										 |  |  | 	if (!(base_and_flags & HIO_FMT_INTMAX_NONULL)) *bp = '\0'; | 
					
						
							| 
									
										
										
										
											2020-02-20 06:48:43 +00:00
										 |  |  | 	return bp - buf; | 
					
						
							|  |  |  | } |