Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/base/nssutf8.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 /* | |
6 * utf8.c | |
7 * | |
8 * This file contains some additional utility routines required for | |
9 * handling UTF8 strings. | |
10 */ | |
11 | |
12 #ifndef BASE_H | |
13 #include "base.h" | |
14 #endif /* BASE_H */ | |
15 | |
16 #include "plstr.h" | |
17 | |
18 /* | |
19 * NOTES: | |
20 * | |
21 * There's an "is hex string" function in pki1/atav.c. If we need | |
22 * it in more places, pull that one out. | |
23 */ | |
24 | |
25 /* | |
26 * nssUTF8_CaseIgnoreMatch | |
27 * | |
28 * Returns true if the two UTF8-encoded strings pointed to by the | |
29 * two specified NSSUTF8 pointers differ only in typcase. | |
30 * | |
31 * The error may be one of the following values: | |
32 * NSS_ERROR_INVALID_POINTER | |
33 * | |
34 * Return value: | |
35 * PR_TRUE if the strings match, ignoring case | |
36 * PR_FALSE if they don't | |
37 * PR_FALSE upon error | |
38 */ | |
39 | |
40 NSS_IMPLEMENT PRBool | |
41 nssUTF8_CaseIgnoreMatch | |
42 ( | |
43 const NSSUTF8 *a, | |
44 const NSSUTF8 *b, | |
45 PRStatus *statusOpt | |
46 ) | |
47 { | |
48 #ifdef NSSDEBUG | |
49 if( ((const NSSUTF8 *)NULL == a) || | |
50 ((const NSSUTF8 *)NULL == b) ) { | |
51 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
52 if( (PRStatus *)NULL != statusOpt ) { | |
53 *statusOpt = PR_FAILURE; | |
54 } | |
55 return PR_FALSE; | |
56 } | |
57 #endif /* NSSDEBUG */ | |
58 | |
59 if( (PRStatus *)NULL != statusOpt ) { | |
60 *statusOpt = PR_SUCCESS; | |
61 } | |
62 | |
63 /* | |
64 * XXX fgmr | |
65 * | |
66 * This is, like, so wrong! | |
67 */ | |
68 if( 0 == PL_strcasecmp((const char *)a, (const char *)b) ) { | |
69 return PR_TRUE; | |
70 } else { | |
71 return PR_FALSE; | |
72 } | |
73 } | |
74 | |
75 /* | |
76 * nssUTF8_PrintableMatch | |
77 * | |
78 * Returns true if the two Printable strings pointed to by the | |
79 * two specified NSSUTF8 pointers match when compared with the | |
80 * rules for Printable String (leading and trailing spaces are | |
81 * disregarded, extents of whitespace match irregardless of length, | |
82 * and case is not significant), then PR_TRUE will be returned. | |
83 * Otherwise, PR_FALSE will be returned. Upon failure, PR_FALSE | |
84 * will be returned. If the optional statusOpt argument is not | |
85 * NULL, then PR_SUCCESS or PR_FAILURE will be stored in that | |
86 * location. | |
87 * | |
88 * The error may be one of the following values: | |
89 * NSS_ERROR_INVALID_POINTER | |
90 * | |
91 * Return value: | |
92 * PR_TRUE if the strings match, ignoring case | |
93 * PR_FALSE if they don't | |
94 * PR_FALSE upon error | |
95 */ | |
96 | |
97 NSS_IMPLEMENT PRBool | |
98 nssUTF8_PrintableMatch | |
99 ( | |
100 const NSSUTF8 *a, | |
101 const NSSUTF8 *b, | |
102 PRStatus *statusOpt | |
103 ) | |
104 { | |
105 PRUint8 *c; | |
106 PRUint8 *d; | |
107 | |
108 #ifdef NSSDEBUG | |
109 if( ((const NSSUTF8 *)NULL == a) || | |
110 ((const NSSUTF8 *)NULL == b) ) { | |
111 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
112 if( (PRStatus *)NULL != statusOpt ) { | |
113 *statusOpt = PR_FAILURE; | |
114 } | |
115 return PR_FALSE; | |
116 } | |
117 #endif /* NSSDEBUG */ | |
118 | |
119 if( (PRStatus *)NULL != statusOpt ) { | |
120 *statusOpt = PR_SUCCESS; | |
121 } | |
122 | |
123 c = (PRUint8 *)a; | |
124 d = (PRUint8 *)b; | |
125 | |
126 while( ' ' == *c ) { | |
127 c++; | |
128 } | |
129 | |
130 while( ' ' == *d ) { | |
131 d++; | |
132 } | |
133 | |
134 while( ('\0' != *c) && ('\0' != *d) ) { | |
135 PRUint8 e, f; | |
136 | |
137 e = *c; | |
138 f = *d; | |
139 | |
140 if( ('a' <= e) && (e <= 'z') ) { | |
141 e -= ('a' - 'A'); | |
142 } | |
143 | |
144 if( ('a' <= f) && (f <= 'z') ) { | |
145 f -= ('a' - 'A'); | |
146 } | |
147 | |
148 if( e != f ) { | |
149 return PR_FALSE; | |
150 } | |
151 | |
152 c++; | |
153 d++; | |
154 | |
155 if( ' ' == *c ) { | |
156 while( ' ' == *c ) { | |
157 c++; | |
158 } | |
159 c--; | |
160 } | |
161 | |
162 if( ' ' == *d ) { | |
163 while( ' ' == *d ) { | |
164 d++; | |
165 } | |
166 d--; | |
167 } | |
168 } | |
169 | |
170 while( ' ' == *c ) { | |
171 c++; | |
172 } | |
173 | |
174 while( ' ' == *d ) { | |
175 d++; | |
176 } | |
177 | |
178 if( *c == *d ) { | |
179 /* And both '\0', btw */ | |
180 return PR_TRUE; | |
181 } else { | |
182 return PR_FALSE; | |
183 } | |
184 } | |
185 | |
186 /* | |
187 * nssUTF8_Duplicate | |
188 * | |
189 * This routine duplicates the UTF8-encoded string pointed to by the | |
190 * specified NSSUTF8 pointer. If the optional arenaOpt argument is | |
191 * not null, the memory required will be obtained from that arena; | |
192 * otherwise, the memory required will be obtained from the heap. | |
193 * A pointer to the new string will be returned. In case of error, | |
194 * an error will be placed on the error stack and NULL will be | |
195 * returned. | |
196 * | |
197 * The error may be one of the following values: | |
198 * NSS_ERROR_INVALID_POINTER | |
199 * NSS_ERROR_INVALID_ARENA | |
200 * NSS_ERROR_NO_MEMORY | |
201 */ | |
202 | |
203 NSS_IMPLEMENT NSSUTF8 * | |
204 nssUTF8_Duplicate | |
205 ( | |
206 const NSSUTF8 *s, | |
207 NSSArena *arenaOpt | |
208 ) | |
209 { | |
210 NSSUTF8 *rv; | |
211 PRUint32 len; | |
212 | |
213 #ifdef NSSDEBUG | |
214 if( (const NSSUTF8 *)NULL == s ) { | |
215 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
216 return (NSSUTF8 *)NULL; | |
217 } | |
218 | |
219 if( (NSSArena *)NULL != arenaOpt ) { | |
220 if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) { | |
221 return (NSSUTF8 *)NULL; | |
222 } | |
223 } | |
224 #endif /* NSSDEBUG */ | |
225 | |
226 len = PL_strlen((const char *)s); | |
227 #ifdef PEDANTIC | |
228 if( '\0' != ((const char *)s)[ len ] ) { | |
229 /* must have wrapped, e.g., too big for PRUint32 */ | |
230 nss_SetError(NSS_ERROR_NO_MEMORY); | |
231 return (NSSUTF8 *)NULL; | |
232 } | |
233 #endif /* PEDANTIC */ | |
234 len++; /* zero termination */ | |
235 | |
236 rv = nss_ZAlloc(arenaOpt, len); | |
237 if( (void *)NULL == rv ) { | |
238 return (NSSUTF8 *)NULL; | |
239 } | |
240 | |
241 (void)nsslibc_memcpy(rv, s, len); | |
242 return rv; | |
243 } | |
244 | |
245 /* | |
246 * nssUTF8_Size | |
247 * | |
248 * This routine returns the length in bytes (including the terminating | |
249 * null) of the UTF8-encoded string pointed to by the specified | |
250 * NSSUTF8 pointer. Zero is returned on error. | |
251 * | |
252 * The error may be one of the following values: | |
253 * NSS_ERROR_INVALID_POINTER | |
254 * NSS_ERROR_VALUE_TOO_LARGE | |
255 * | |
256 * Return value: | |
257 * 0 on error | |
258 * nonzero length of the string. | |
259 */ | |
260 | |
261 NSS_IMPLEMENT PRUint32 | |
262 nssUTF8_Size | |
263 ( | |
264 const NSSUTF8 *s, | |
265 PRStatus *statusOpt | |
266 ) | |
267 { | |
268 PRUint32 sv; | |
269 | |
270 #ifdef NSSDEBUG | |
271 if( (const NSSUTF8 *)NULL == s ) { | |
272 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
273 if( (PRStatus *)NULL != statusOpt ) { | |
274 *statusOpt = PR_FAILURE; | |
275 } | |
276 return 0; | |
277 } | |
278 #endif /* NSSDEBUG */ | |
279 | |
280 sv = PL_strlen((const char *)s) + 1; | |
281 #ifdef PEDANTIC | |
282 if( '\0' != ((const char *)s)[ sv-1 ] ) { | |
283 /* wrapped */ | |
284 nss_SetError(NSS_ERROR_VALUE_TOO_LARGE); | |
285 if( (PRStatus *)NULL != statusOpt ) { | |
286 *statusOpt = PR_FAILURE; | |
287 } | |
288 return 0; | |
289 } | |
290 #endif /* PEDANTIC */ | |
291 | |
292 if( (PRStatus *)NULL != statusOpt ) { | |
293 *statusOpt = PR_SUCCESS; | |
294 } | |
295 | |
296 return sv; | |
297 } | |
298 | |
299 /* | |
300 * nssUTF8_Length | |
301 * | |
302 * This routine returns the length in characters (not including the | |
303 * terminating null) of the UTF8-encoded string pointed to by the | |
304 * specified NSSUTF8 pointer. | |
305 * | |
306 * The error may be one of the following values: | |
307 * NSS_ERROR_INVALID_POINTER | |
308 * NSS_ERROR_VALUE_TOO_LARGE | |
309 * NSS_ERROR_INVALID_STRING | |
310 * | |
311 * Return value: | |
312 * length of the string (which may be zero) | |
313 * 0 on error | |
314 */ | |
315 | |
316 NSS_IMPLEMENT PRUint32 | |
317 nssUTF8_Length | |
318 ( | |
319 const NSSUTF8 *s, | |
320 PRStatus *statusOpt | |
321 ) | |
322 { | |
323 PRUint32 l = 0; | |
324 const PRUint8 *c = (const PRUint8 *)s; | |
325 | |
326 #ifdef NSSDEBUG | |
327 if( (const NSSUTF8 *)NULL == s ) { | |
328 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
329 goto loser; | |
330 } | |
331 #endif /* NSSDEBUG */ | |
332 | |
333 /* | |
334 * From RFC 2044: | |
335 * | |
336 * UCS-4 range (hex.) UTF-8 octet sequence (binary) | |
337 * 0000 0000-0000 007F 0xxxxxxx | |
338 * 0000 0080-0000 07FF 110xxxxx 10xxxxxx | |
339 * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx | |
340 * 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | |
341 * 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx | |
342 * 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx | |
343 */ | |
344 | |
345 while( 0 != *c ) { | |
346 PRUint32 incr; | |
347 if( (*c & 0x80) == 0 ) { | |
348 incr = 1; | |
349 } else if( (*c & 0xE0) == 0xC0 ) { | |
350 incr = 2; | |
351 } else if( (*c & 0xF0) == 0xE0 ) { | |
352 incr = 3; | |
353 } else if( (*c & 0xF8) == 0xF0 ) { | |
354 incr = 4; | |
355 } else if( (*c & 0xFC) == 0xF8 ) { | |
356 incr = 5; | |
357 } else if( (*c & 0xFE) == 0xFC ) { | |
358 incr = 6; | |
359 } else { | |
360 nss_SetError(NSS_ERROR_INVALID_STRING); | |
361 goto loser; | |
362 } | |
363 | |
364 l += incr; | |
365 | |
366 #ifdef PEDANTIC | |
367 if( l < incr ) { | |
368 /* Wrapped-- too big */ | |
369 nss_SetError(NSS_ERROR_VALUE_TOO_LARGE); | |
370 goto loser; | |
371 } | |
372 | |
373 { | |
374 PRUint8 *d; | |
375 for( d = &c[1]; d < &c[incr]; d++ ) { | |
376 if( (*d & 0xC0) != 0xF0 ) { | |
377 nss_SetError(NSS_ERROR_INVALID_STRING); | |
378 goto loser; | |
379 } | |
380 } | |
381 } | |
382 #endif /* PEDANTIC */ | |
383 | |
384 c += incr; | |
385 } | |
386 | |
387 if( (PRStatus *)NULL != statusOpt ) { | |
388 *statusOpt = PR_SUCCESS; | |
389 } | |
390 | |
391 return l; | |
392 | |
393 loser: | |
394 if( (PRStatus *)NULL != statusOpt ) { | |
395 *statusOpt = PR_FAILURE; | |
396 } | |
397 | |
398 return 0; | |
399 } | |
400 | |
401 | |
402 /* | |
403 * nssUTF8_Create | |
404 * | |
405 * This routine creates a UTF8 string from a string in some other | |
406 * format. Some types of string may include embedded null characters, | |
407 * so for them the length parameter must be used. For string types | |
408 * that are null-terminated, the length parameter is optional; if it | |
409 * is zero, it will be ignored. If the optional arena argument is | |
410 * non-null, the memory used for the new string will be obtained from | |
411 * that arena, otherwise it will be obtained from the heap. This | |
412 * routine may return NULL upon error, in which case it will have | |
413 * placed an error on the error stack. | |
414 * | |
415 * The error may be one of the following: | |
416 * NSS_ERROR_INVALID_POINTER | |
417 * NSS_ERROR_NO_MEMORY | |
418 * NSS_ERROR_UNSUPPORTED_TYPE | |
419 * | |
420 * Return value: | |
421 * NULL upon error | |
422 * A non-null pointer to a new UTF8 string otherwise | |
423 */ | |
424 | |
425 extern const NSSError NSS_ERROR_INTERNAL_ERROR; /* XXX fgmr */ | |
426 | |
427 NSS_IMPLEMENT NSSUTF8 * | |
428 nssUTF8_Create | |
429 ( | |
430 NSSArena *arenaOpt, | |
431 nssStringType type, | |
432 const void *inputString, | |
433 PRUint32 size /* in bytes, not characters */ | |
434 ) | |
435 { | |
436 NSSUTF8 *rv = NULL; | |
437 | |
438 #ifdef NSSDEBUG | |
439 if( (NSSArena *)NULL != arenaOpt ) { | |
440 if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) { | |
441 return (NSSUTF8 *)NULL; | |
442 } | |
443 } | |
444 | |
445 if( (const void *)NULL == inputString ) { | |
446 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
447 return (NSSUTF8 *)NULL; | |
448 } | |
449 #endif /* NSSDEBUG */ | |
450 | |
451 switch( type ) { | |
452 case nssStringType_DirectoryString: | |
453 /* This is a composite type requiring BER */ | |
454 nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE); | |
455 break; | |
456 case nssStringType_TeletexString: | |
457 /* | |
458 * draft-ietf-pkix-ipki-part1-11 says in part: | |
459 * | |
460 * In addition, many legacy implementations support names encoded | |
461 * in the ISO 8859-1 character set (Latin1String) but tag them as | |
462 * TeletexString. The Latin1String includes characters used in | |
463 * Western European countries which are not part of the | |
464 * TeletexString charcter set. Implementations that process | |
465 * TeletexString SHOULD be prepared to handle the entire ISO | |
466 * 8859-1 character set.[ISO 8859-1]. | |
467 */ | |
468 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
469 break; | |
470 case nssStringType_PrintableString: | |
471 /* | |
472 * PrintableString consists of A-Za-z0-9 ,()+,-./:=? | |
473 * This is a subset of ASCII, which is a subset of UTF8. | |
474 * So we can just duplicate the string over. | |
475 */ | |
476 | |
477 if( 0 == size ) { | |
478 rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt); | |
479 } else { | |
480 rv = nss_ZAlloc(arenaOpt, size+1); | |
481 if( (NSSUTF8 *)NULL == rv ) { | |
482 return (NSSUTF8 *)NULL; | |
483 } | |
484 | |
485 (void)nsslibc_memcpy(rv, inputString, size); | |
486 } | |
487 | |
488 break; | |
489 case nssStringType_UniversalString: | |
490 /* 4-byte unicode */ | |
491 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
492 break; | |
493 case nssStringType_BMPString: | |
494 /* Base Multilingual Plane of Unicode */ | |
495 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
496 break; | |
497 case nssStringType_UTF8String: | |
498 if( 0 == size ) { | |
499 rv = nssUTF8_Duplicate((const NSSUTF8 *)inputString, arenaOpt); | |
500 } else { | |
501 rv = nss_ZAlloc(arenaOpt, size+1); | |
502 if( (NSSUTF8 *)NULL == rv ) { | |
503 return (NSSUTF8 *)NULL; | |
504 } | |
505 | |
506 (void)nsslibc_memcpy(rv, inputString, size); | |
507 } | |
508 | |
509 break; | |
510 case nssStringType_PHGString: | |
511 /* | |
512 * PHGString is an IA5String (with case-insensitive comparisons). | |
513 * IA5 is ~almost~ ascii; ascii has dollar-sign where IA5 has | |
514 * currency symbol. | |
515 */ | |
516 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
517 break; | |
518 case nssStringType_GeneralString: | |
519 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
520 break; | |
521 default: | |
522 nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE); | |
523 break; | |
524 } | |
525 | |
526 return rv; | |
527 } | |
528 | |
529 NSS_IMPLEMENT NSSItem * | |
530 nssUTF8_GetEncoding | |
531 ( | |
532 NSSArena *arenaOpt, | |
533 NSSItem *rvOpt, | |
534 nssStringType type, | |
535 NSSUTF8 *string | |
536 ) | |
537 { | |
538 NSSItem *rv = (NSSItem *)NULL; | |
539 PRStatus status = PR_SUCCESS; | |
540 | |
541 #ifdef NSSDEBUG | |
542 if( (NSSArena *)NULL != arenaOpt ) { | |
543 if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) { | |
544 return (NSSItem *)NULL; | |
545 } | |
546 } | |
547 | |
548 if( (NSSUTF8 *)NULL == string ) { | |
549 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
550 return (NSSItem *)NULL; | |
551 } | |
552 #endif /* NSSDEBUG */ | |
553 | |
554 switch( type ) { | |
555 case nssStringType_DirectoryString: | |
556 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
557 break; | |
558 case nssStringType_TeletexString: | |
559 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
560 break; | |
561 case nssStringType_PrintableString: | |
562 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
563 break; | |
564 case nssStringType_UniversalString: | |
565 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
566 break; | |
567 case nssStringType_BMPString: | |
568 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
569 break; | |
570 case nssStringType_UTF8String: | |
571 { | |
572 NSSUTF8 *dup = nssUTF8_Duplicate(string, arenaOpt); | |
573 if( (NSSUTF8 *)NULL == dup ) { | |
574 return (NSSItem *)NULL; | |
575 } | |
576 | |
577 if( (NSSItem *)NULL == rvOpt ) { | |
578 rv = nss_ZNEW(arenaOpt, NSSItem); | |
579 if( (NSSItem *)NULL == rv ) { | |
580 (void)nss_ZFreeIf(dup); | |
581 return (NSSItem *)NULL; | |
582 } | |
583 } else { | |
584 rv = rvOpt; | |
585 } | |
586 | |
587 rv->data = dup; | |
588 dup = (NSSUTF8 *)NULL; | |
589 rv->size = nssUTF8_Size(rv->data, &status); | |
590 if( (0 == rv->size) && (PR_SUCCESS != status) ) { | |
591 if( (NSSItem *)NULL == rvOpt ) { | |
592 (void)nss_ZFreeIf(rv); | |
593 } | |
594 return (NSSItem *)NULL; | |
595 } | |
596 } | |
597 break; | |
598 case nssStringType_PHGString: | |
599 nss_SetError(NSS_ERROR_INTERNAL_ERROR); /* unimplemented */ | |
600 break; | |
601 default: | |
602 nss_SetError(NSS_ERROR_UNSUPPORTED_TYPE); | |
603 break; | |
604 } | |
605 | |
606 return rv; | |
607 } | |
608 | |
609 /* | |
610 * nssUTF8_CopyIntoFixedBuffer | |
611 * | |
612 * This will copy a UTF8 string into a fixed-length buffer, making | |
613 * sure that the all characters are valid. Any remaining space will | |
614 * be padded with the specified ASCII character, typically either | |
615 * null or space. | |
616 * | |
617 * Blah, blah, blah. | |
618 */ | |
619 | |
620 NSS_IMPLEMENT PRStatus | |
621 nssUTF8_CopyIntoFixedBuffer | |
622 ( | |
623 NSSUTF8 *string, | |
624 char *buffer, | |
625 PRUint32 bufferSize, | |
626 char pad | |
627 ) | |
628 { | |
629 PRUint32 stringSize = 0; | |
630 | |
631 #ifdef NSSDEBUG | |
632 if( (char *)NULL == buffer ) { | |
633 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
634 return PR_FALSE; | |
635 } | |
636 | |
637 if( 0 == bufferSize ) { | |
638 nss_SetError(NSS_ERROR_INVALID_ARGUMENT); | |
639 return PR_FALSE; | |
640 } | |
641 | |
642 if( (pad & 0x80) != 0x00 ) { | |
643 nss_SetError(NSS_ERROR_INVALID_ARGUMENT); | |
644 return PR_FALSE; | |
645 } | |
646 #endif /* NSSDEBUG */ | |
647 | |
648 if( (NSSUTF8 *)NULL == string ) { | |
649 string = (NSSUTF8 *) ""; | |
650 } | |
651 | |
652 stringSize = nssUTF8_Size(string, (PRStatus *)NULL); | |
653 stringSize--; /* don't count the trailing null */ | |
654 if( stringSize > bufferSize ) { | |
655 PRUint32 bs = bufferSize; | |
656 (void)nsslibc_memcpy(buffer, string, bufferSize); | |
657 | |
658 if( ( ((buffer[ bs-1 ] & 0x80) == 0x00)) || | |
659 ((bs > 1) && ((buffer[ bs-2 ] & 0xE0) == 0xC0)) || | |
660 ((bs > 2) && ((buffer[ bs-3 ] & 0xF0) == 0xE0)) || | |
661 ((bs > 3) && ((buffer[ bs-4 ] & 0xF8) == 0xF0)) || | |
662 ((bs > 4) && ((buffer[ bs-5 ] & 0xFC) == 0xF8)) || | |
663 ((bs > 5) && ((buffer[ bs-6 ] & 0xFE) == 0xFC)) ) { | |
664 /* It fit exactly */ | |
665 return PR_SUCCESS; | |
666 } | |
667 | |
668 /* Too long. We have to trim the last character */ | |
669 for( /*bs*/; bs != 0; bs-- ) { | |
670 if( (buffer[bs-1] & 0xC0) != 0x80 ) { | |
671 buffer[bs-1] = pad; | |
672 break; | |
673 } else { | |
674 buffer[bs-1] = pad; | |
675 } | |
676 } | |
677 } else { | |
678 (void)nsslibc_memset(buffer, pad, bufferSize); | |
679 (void)nsslibc_memcpy(buffer, string, stringSize); | |
680 } | |
681 | |
682 return PR_SUCCESS; | |
683 } | |
684 | |
685 /* | |
686 * nssUTF8_Equal | |
687 * | |
688 */ | |
689 | |
690 NSS_IMPLEMENT PRBool | |
691 nssUTF8_Equal | |
692 ( | |
693 const NSSUTF8 *a, | |
694 const NSSUTF8 *b, | |
695 PRStatus *statusOpt | |
696 ) | |
697 { | |
698 PRUint32 la, lb; | |
699 | |
700 #ifdef NSSDEBUG | |
701 if( ((const NSSUTF8 *)NULL == a) || | |
702 ((const NSSUTF8 *)NULL == b) ) { | |
703 nss_SetError(NSS_ERROR_INVALID_POINTER); | |
704 if( (PRStatus *)NULL != statusOpt ) { | |
705 *statusOpt = PR_FAILURE; | |
706 } | |
707 return PR_FALSE; | |
708 } | |
709 #endif /* NSSDEBUG */ | |
710 | |
711 la = nssUTF8_Size(a, statusOpt); | |
712 if( 0 == la ) { | |
713 return PR_FALSE; | |
714 } | |
715 | |
716 lb = nssUTF8_Size(b, statusOpt); | |
717 if( 0 == lb ) { | |
718 return PR_FALSE; | |
719 } | |
720 | |
721 if( la != lb ) { | |
722 return PR_FALSE; | |
723 } | |
724 | |
725 return nsslibc_memequal(a, b, la, statusOpt); | |
726 } |