xref: /dflybsd-src/lib/libc/locale/fix_grouping.c (revision f45ae2bfb2cea6cc77aee4babd1a2e974964c058)
10d5acd74SJohn Marino /*
20d5acd74SJohn Marino  * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
30d5acd74SJohn Marino  * All rights reserved.
40d5acd74SJohn Marino  *
50d5acd74SJohn Marino  * Redistribution and use in source and binary forms, with or without
60d5acd74SJohn Marino  * modification, are permitted provided that the following conditions
70d5acd74SJohn Marino  * are met:
80d5acd74SJohn Marino  * 1. Redistributions of source code must retain the above copyright
90d5acd74SJohn Marino  *    notice, this list of conditions and the following disclaimer.
100d5acd74SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
110d5acd74SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
120d5acd74SJohn Marino  *    documentation and/or other materials provided with the distribution.
130d5acd74SJohn Marino  *
140d5acd74SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
150d5acd74SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
160d5acd74SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
170d5acd74SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
180d5acd74SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
190d5acd74SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
200d5acd74SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
210d5acd74SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
220d5acd74SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
230d5acd74SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
240d5acd74SJohn Marino  * SUCH DAMAGE.
250d5acd74SJohn Marino  *
260d5acd74SJohn Marino  * $FreeBSD: head/lib/libc/locale/fix_grouping.c 116875 2003-06-26 10:46:16Z phantom $
270d5acd74SJohn Marino  */
280d5acd74SJohn Marino 
290d5acd74SJohn Marino #include <ctype.h>
300d5acd74SJohn Marino #include <limits.h>
310d5acd74SJohn Marino #include <stddef.h>
320d5acd74SJohn Marino 
33*f45ae2bfSSascha Wildner const char *__fix_locale_grouping_str(const char *);
34*f45ae2bfSSascha Wildner 
350d5acd74SJohn Marino static const char nogrouping[] = { CHAR_MAX, '\0' };
360d5acd74SJohn Marino 
370d5acd74SJohn Marino /*
380d5acd74SJohn Marino  * Internal helper used to convert grouping sequences from string
390d5acd74SJohn Marino  * representation into POSIX specified form, i.e.
400d5acd74SJohn Marino  *
410d5acd74SJohn Marino  * "3;3;-1" -> "\003\003\177\000"
420d5acd74SJohn Marino  */
430d5acd74SJohn Marino 
440d5acd74SJohn Marino const char *
__fix_locale_grouping_str(const char * str)450d5acd74SJohn Marino __fix_locale_grouping_str(const char *str)
460d5acd74SJohn Marino {
470d5acd74SJohn Marino 	char *src, *dst;
480d5acd74SJohn Marino 	char n;
490d5acd74SJohn Marino 
500d5acd74SJohn Marino 	if (str == NULL || *str == '\0') {
510d5acd74SJohn Marino 		return nogrouping;
520d5acd74SJohn Marino 	}
530d5acd74SJohn Marino 
540d5acd74SJohn Marino 	for (src = (char*)str, dst = (char*)str; *src != '\0'; src++) {
550d5acd74SJohn Marino 
560d5acd74SJohn Marino 		/* input string examples: "3;3", "3;2;-1" */
570d5acd74SJohn Marino 		if (*src == ';')
580d5acd74SJohn Marino 			continue;
590d5acd74SJohn Marino 
600d5acd74SJohn Marino 		if (*src == '-' && *(src+1) == '1') {
610d5acd74SJohn Marino 			*dst++ = CHAR_MAX;
620d5acd74SJohn Marino 			src++;
630d5acd74SJohn Marino 			continue;
640d5acd74SJohn Marino 		}
650d5acd74SJohn Marino 
660d5acd74SJohn Marino 		if (!isdigit((unsigned char)*src)) {
670d5acd74SJohn Marino 			/* broken grouping string */
680d5acd74SJohn Marino 			return nogrouping;
690d5acd74SJohn Marino 		}
700d5acd74SJohn Marino 
710d5acd74SJohn Marino 		/* assume all numbers <= 99 */
720d5acd74SJohn Marino 		n = *src - '0';
730d5acd74SJohn Marino 		if (isdigit((unsigned char)*(src+1))) {
740d5acd74SJohn Marino 			src++;
750d5acd74SJohn Marino 			n *= 10;
760d5acd74SJohn Marino 			n += *src - '0';
770d5acd74SJohn Marino 		}
780d5acd74SJohn Marino 
790d5acd74SJohn Marino 		*dst = n;
800d5acd74SJohn Marino 		/* NOTE: assume all input started with "0" as 'no grouping' */
810d5acd74SJohn Marino 		if (*dst == '\0')
820d5acd74SJohn Marino 			return (dst == (char*)str) ? nogrouping : str;
830d5acd74SJohn Marino 		dst++;
840d5acd74SJohn Marino 	}
850d5acd74SJohn Marino 	*dst = '\0';
860d5acd74SJohn Marino 	return str;
870d5acd74SJohn Marino }
88