xref: /illumos-gate/usr/src/common/ficl/utility.c (revision ea4c6b78cebe2a3687fa43deeedf6212a124d817)
1 #include "ficl.h"
2 
3 /*
4  * a l i g n P t r
5  * Aligns the given pointer to FICL_ALIGN address units.
6  * Returns the aligned pointer value.
7  */
8 void *
9 ficlAlignPointer(void *ptr)
10 {
11 #if FICL_PLATFORM_ALIGNMENT > 1
12 	intptr_t p = (intptr_t)ptr;
13 
14 	if (p & (FICL_PLATFORM_ALIGNMENT - 1))
15 		ptr = (void *)((p & ~(FICL_PLATFORM_ALIGNMENT - 1)) +
16 		    FICL_PLATFORM_ALIGNMENT);
17 #endif
18 	return (ptr);
19 }
20 
21 /*
22  * s t r r e v
23  */
24 char *
25 ficlStringReverse(char *string)
26 {
27 	int i = strlen(string);
28 	char *p1 = string;		/* first char of string */
29 	char *p2 = string + i - 1;	/* last non-NULL char of string */
30 	char c;
31 
32 	if (i > 1) {
33 		while (p1 < p2) {
34 			c = *p2;
35 			*p2 = *p1;
36 			*p1 = c;
37 			p1++; p2--;
38 		}
39 	}
40 
41 	return (string);
42 }
43 
44 /*
45  * d i g i t _ t o _ c h a r
46  */
47 static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
48 
49 char
50 ficlDigitToCharacter(int value)
51 {
52 	return (digits[value]);
53 }
54 
55 /*
56  * i s P o w e r O f T w o
57  * Tests whether supplied argument is an integer power of 2 (2**n)
58  * where 32 > n > 1, and returns n if so. Otherwise returns zero.
59  */
60 int
61 ficlIsPowerOfTwo(ficlUnsigned u)
62 {
63 	int i = 1;
64 	ficlUnsigned t = 2;
65 
66 	for (; ((t <= u) && (t != 0)); i++, t <<= 1) {
67 		if (u == t)
68 			return (i);
69 	}
70 
71 	return (0);
72 }
73 
74 /*
75  * l t o a
76  */
77 char *
78 ficlLtoa(ficlInteger value, char *string, int radix)
79 {
80 	char *cp = string;
81 	int sign = ((radix == 10) && (value < 0));
82 	int pwr;
83 
84 	FICL_ASSERT(NULL, radix > 1);
85 	FICL_ASSERT(NULL, radix < 37);
86 	FICL_ASSERT(NULL, string);
87 
88 	pwr = ficlIsPowerOfTwo((ficlUnsigned)radix);
89 
90 	if (sign)
91 		value = -value;
92 
93 	if (value == 0)
94 		*cp++ = '0';
95 	else if (pwr != 0) {
96 		ficlUnsigned v = (ficlUnsigned) value;
97 		ficlUnsigned mask = (ficlUnsigned) ~(-1 << pwr);
98 		while (v) {
99 			*cp++ = digits[v & mask];
100 			v >>= pwr;
101 		}
102 	} else {
103 		ficl2UnsignedQR result;
104 		ficl2Unsigned v;
105 		FICL_UNSIGNED_TO_2UNSIGNED((ficlUnsigned)value, v);
106 		while (FICL_2UNSIGNED_NOT_ZERO(v)) {
107 			result = ficl2UnsignedDivide(v, (ficlUnsigned)radix);
108 			*cp++ = digits[result.remainder];
109 			v = result.quotient;
110 		}
111 	}
112 
113 	if (sign)
114 		*cp++ = '-';
115 
116 	*cp++ = '\0';
117 
118 	return (ficlStringReverse(string));
119 }
120 
121 /*
122  * u l t o a
123  */
124 char *
125 ficlUltoa(ficlUnsigned value, char *string, int radix)
126 {
127 	char *cp = string;
128 	ficl2Unsigned ud;
129 	ficl2UnsignedQR result;
130 
131 	FICL_ASSERT(NULL, radix > 1);
132 	FICL_ASSERT(NULL, radix < 37);
133 	FICL_ASSERT(NULL, string);
134 
135 	if (value == 0)
136 		*cp++ = '0';
137 	else {
138 		FICL_UNSIGNED_TO_2UNSIGNED(value, ud);
139 		while (FICL_2UNSIGNED_NOT_ZERO(ud)) {
140 			result = ficl2UnsignedDivide(ud, (ficlUnsigned)radix);
141 			ud = result.quotient;
142 			*cp++ = digits[result.remainder];
143 		}
144 	}
145 
146 	*cp++ = '\0';
147 
148 	return (ficlStringReverse(string));
149 }
150 
151 /*
152  * c a s e F o l d
153  * Case folds a NULL terminated string in place. All characters
154  * get converted to lower case.
155  */
156 char *
157 ficlStringCaseFold(char *cp)
158 {
159 	char *oldCp = cp;
160 
161 	while (*cp) {
162 		if (isupper((unsigned char)*cp))
163 			*cp = (char)tolower((unsigned char)*cp);
164 		cp++;
165 	}
166 
167 	return (oldCp);
168 }
169 
170 /*
171  * s t r i n c m p
172  * (jws) simplified the code a bit in hopes of appeasing Purify
173  */
174 int
175 ficlStrincmp(char *cp1, char *cp2, ficlUnsigned count)
176 {
177 	int i = 0;
178 
179 	for (; 0 < count; ++cp1, ++cp2, --count) {
180 		i = tolower((unsigned char)*cp1) - tolower((unsigned char)*cp2);
181 		if (i != 0)
182 			return (i);
183 		else if (*cp1 == '\0')
184 			return (0);
185 	}
186 	return (0);
187 }
188 
189 /*
190  * s k i p S p a c e
191  * Given a string pointer, returns a pointer to the first non-space
192  * char of the string, or to the NULL terminator if no such char found.
193  * If the pointer reaches "end" first, stop there. Pass NULL to
194  * suppress this behavior.
195  */
196 char *
197 ficlStringSkipSpace(char *cp, char *end)
198 {
199 	FICL_ASSERT(NULL, cp);
200 
201 	while ((cp != end) && isspace((unsigned char)*cp))
202 		cp++;
203 
204 	return (cp);
205 }
206 
207 void
208 ficlCompatibilityTextOutCallback(ficlCallback *callback, char *text,
209     ficlCompatibilityOutputFunction outputFunction)
210 {
211 	char buffer[256];
212 	char *bufferStop = buffer + sizeof (buffer) - 1;
213 
214 	if (text == NULL) {
215 		outputFunction(callback->vm, NULL, 0 /* false */);
216 		return;
217 	}
218 
219 	while (*text) {
220 		int newline = 0 /* false */;
221 		char *trace = buffer;
222 		while ((*text) && (trace < bufferStop)) {
223 			switch (*text) {
224 			/* throw away \r */
225 			case '\r':
226 				text++;
227 			continue;
228 			case '\n':
229 				text++;
230 				newline = !0 /* true */;
231 			break;
232 			default:
233 				*trace++ = *text++;
234 			break;
235 			}
236 		}
237 
238 		*trace = 0;
239 		(outputFunction)(callback->vm, buffer, newline);
240 	}
241 }
242