Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
valcmp.cpp
Go to the documentation of this file.
1
27// expand _TEST_EXPORT macros
28#define _RWSTD_TEST_SRC
29
30#include <rw_valcmp.h>
31
32#include <stdio.h> // for fprintf, stderr
33#include <stdlib.h> // for abort
34#include <string.h> // for memcmp
35
36
38typedef unsigned char UChar;
39
40
41static const UChar
42_rw_upper [] = {
43
44#if 'A' == 0x41
45
46 // basic ASCII:
47 // .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f
48 // --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
49 // NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI
50 /* 0. */ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
51 // DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
52 /* 1. */ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
53 // SPC ! " # $ % ' ' ( ) * + , - . /
54 /* 2. */ "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
55 // 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
56 /* 3. */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
57 // A B C D E F G H I J K L M N O
58 /* 4. */ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
59 // P Q R S T U V W X Y Z [ \ ] ^ _
60 /* 5. */ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
61 // ` a b c d e f g h i j k l m n o
62 /* 6. */ "\x60\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
63 // p q r s t u v w x y z { | } ~ DEL
64 /* 7. */ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x7b\x7c\x7d\x7e\x7f"
65
66 // extended ASCII:
67 /* 8. */ "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
68 /* 9. */ "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
69 /* a. */ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
70 /* b. */ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
71 /* c. */ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
72 /* d. */ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
73 /* e. */ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
74 /* f. */ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
75
76#elif 'A' == 0xc1
77
78 // EBCDIC:
79 // .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f
80 // --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
81 // NUL SOH STX ETX PF HT LC DEL SMM VT FF CR SO SI
82 /* 0. */ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
83 // DLE DC1 DC2 TM RES NL BS IL CAN EM CC CU1 IFS IGS IRS IUS
84 /* 1. */ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
85 // DS SOS FS BYP LF ETB ESC SM CU2 ENQ ACK BEL
86 /* 2. */ "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
87 // SYN PN RS UC EOT CU3 DC4 NAK SUB
88 /* 3. */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
89 // SP ct. . < ( + |
90 /* 4. */ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
91 // & ! $ * ) ; ~
92 /* 5. */ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
93 // - / , % _ > ?
94 /* 6. */ "\x60\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
95 // : # @ ' = "
96 /* 7. */ "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
97 // a b c d e f g h i
98 /* 8. */ "\x80\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\x8a\x8b\x8c\x8d\x8e\x8f"
99 // j k l m n o p q r
100 /* 9. */ "\x90\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\x9a\x9b\x9c\x9d\x9e\x9f"
101 // s t u v w x y z
102 /* a. */ "\xa0\xa1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xaa\xab\xac\xad\xae\xaf"
103 // `
104 /* b. */ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
105 // A B C D E F G H I
106 /* c. */ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
107 // J K L M N O P Q R
108 /* d. */ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
109 // S T U V W X Y Z
110 /* e. */ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
111 // 0 1 2 3 4 5 6 7 8 9
112 /* f. */ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
113
114#else // 'A' != 0x41 && 'A' != 0xc1
115# error unknown character set (neither ASCII nor EBCDIC)
116#endif // ASCII or EBCDIC
117
118};
119
120
121// returns 1 iff all size bytes of the object pointed to by buf are 0
122static int
123_rw_iszero (const void *buf, size_t size)
124{
125 for (size_t i = 0; i != size; ++i)
126 if (_RWSTD_STATIC_CAST (const UChar*, buf)[i])
127 return 0;
128
129 return 1;
130}
131
132
133// compares two objects of equal size
134static int
135_rw_cmpx (const void *buf1,
136 const void *buf2,
137 size_t nelems,
138 size_t size,
139 int flags = 0)
140{
141 const UChar *p1 = _RWSTD_STATIC_CAST (const UChar*, buf1);
142 const UChar *p2 = _RWSTD_STATIC_CAST (const UChar*, buf2);
143
144 int ret = 0;
145
146 for ( ; nelems; p1 += size, p2 += size, --nelems) {
147
148 ret = memcmp (p1, p2, size);
149
150 if (flags & CMP_NULTERM) {
151
152 const int zero1 = _rw_iszero (p1, size);
153 const int zero2 = _rw_iszero (p2, size);
154
155 if (zero1 || zero2) {
156 ret = zero1 - zero2;
157 break;
158 }
159 }
160
161 if (ret && (flags & CMP_NOCASE)) {
162 // FIXME: implement
163 fprintf (stderr,
164 "%s:%d: case insensitive comparison not implemented\n",
165 __FILE__, __LINE__);
166 abort ();
167 }
168 }
169
170 if (flags & CMP_RETOFF) {
171 // FIXME: implement
172 fprintf (stderr,
173 "%s:%d: returning offset not implemented\n",
174 __FILE__, __LINE__);
175 abort ();
176 }
177
178 return ret < 0 ? -1 : ret ? +1 : 0;
179}
180
181
182// compares two byte arrays
183static int
184_rw_cmp1 (const void *buf1,
185 const void *buf2,
186 size_t nelems,
187 int flags = 0)
188{
189#ifdef _RWSTD_UINT8_T
190
191 typedef _RWSTD_UINT8_T UI8T;
192
193 if (0 == flags) {
194 const int ret = memcmp (buf1, buf2, nelems);
195 return ret < 0 ? -1 : ret ? +1 : 0;
196 }
197
198 if (CMP_NULTERM == flags) {
199 const int ret =
200 strncmp (_RWSTD_STATIC_CAST (const char*, buf1),
201 _RWSTD_STATIC_CAST (const char*, buf2),
202 nelems);
203 return ret < 0 ? -1 : ret ? +1 : 0;
204 }
205
206 size_t inx = 0;
207 int ret = 0;
208
209 const UI8T *pi1 = _RWSTD_STATIC_CAST (const UI8T*, buf1);
210 const UI8T *pi2 = _RWSTD_STATIC_CAST (const UI8T*, buf2);
211
212 for (; inx < nelems; ++pi1, ++pi2, ++inx) {
213
214 const UI8T ui1 = *pi1;
215 const UI8T ui2 = *pi2;
216
217 if (flags & CMP_NULTERM) {
218
219 if (0 == ui1) {
220 ret = ui2 ? -1 : 0;
221 break;
222 }
223
224 if (0 == ui2) {
225 ret = +1;
226 break;
227 }
228 }
229
230 if (ui1 != ui2) {
231 if (flags & CMP_NOCASE) {
232 if (_rw_upper [ui1] != _rw_upper [ui2]) {
233 ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
234 break;
235 }
236 }
237 else {
238 ret = ui1 < ui2 ? -1 : +1;
239 break;
240 }
241 }
242 }
243
244 if (CMP_RETOFF & flags) {
245 ret = ret ? int (inx) : -1;
246 }
247
248 return ret;
249
250#else // if !defined (_RWSTD_UINT8_T)
251# error _RWSTD_UINT8_T not #defined (configuration problem?)
252#endif // _RWSTD_UINT8_T
253
254}
255
256
257// compares two arrays of objects each 16 bits in size
258static int
259_rw_cmp2 (const void *buf1,
260 const void *buf2,
261 size_t nelems,
262 int flags = 0)
263{
264#ifdef _RWSTD_UINT16_T
265
266 typedef _RWSTD_UINT16_T UI16T;
267
268 size_t inx = 0;
269 int ret = 0;
270
271 const UI16T *pi1 = _RWSTD_STATIC_CAST (const UI16T*, buf1);
272 const UI16T *pi2 = _RWSTD_STATIC_CAST (const UI16T*, buf2);
273
274 for (; inx < nelems; ++pi1, ++pi2, ++inx) {
275
276 const UI16T ui1 = *pi1;
277 const UI16T ui2 = *pi2;
278
279 if (flags & CMP_NULTERM) {
280
281 if (0 == ui1) {
282 ret = ui2 ? -1 : 0;
283 break;
284 }
285
286 if (0 == ui2) {
287 ret = +1;
288 break;
289 }
290 }
291
292 if (ui1 != ui2) {
293 if (flags & CMP_NOCASE) {
294 if (_RWSTD_UCHAR_MAX < ui1 || _RWSTD_UCHAR_MAX < ui2) {
295 ret = ui1 < ui2 ? -1 : +1;
296 break;
297 }
298 else if (_rw_upper [ui1] != _rw_upper [ui2]) {
299 ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
300 break;
301 }
302 }
303 else {
304 ret = ui1 < ui2 ? -1 : +1;
305 break;
306 }
307 }
308 }
309
310 if (CMP_RETOFF & flags) {
311 ret = ret ? int (inx) : -1;
312 }
313
314 return ret;
315
316#else // if !defined (_RWSTD_UINT16_T)
317
318 return _rw_cmpx (buf1, buf2, nelems, 2, flags);
319
320#endif // _RWSTD_UINT16_T
321}
322
323
324// compares two arrays of objects each 32 bits in size
325static int
326_rw_cmp4 (const void *buf1,
327 const void *buf2,
328 size_t nelems,
329 int flags = 0)
330{
331#ifdef _RWSTD_UINT32_T
332
333 typedef _RWSTD_UINT32_T UI32T;
334
335 size_t inx = 0;
336 int ret = 0;
337
338 const UI32T *pi1 = _RWSTD_STATIC_CAST (const UI32T*, buf1);
339 const UI32T *pi2 = _RWSTD_STATIC_CAST (const UI32T*, buf2);
340
341 for (; inx < nelems; ++pi1, ++pi2, ++inx) {
342
343 const UI32T ui1 = *pi1;
344 const UI32T ui2 = *pi2;
345
346 if (flags & CMP_NULTERM) {
347
348 if (0 == ui1) {
349 ret = ui2 ? -1 : 0;
350 break;
351 }
352
353 if (0 == ui2) {
354 ret = +1;
355 break;
356 }
357 }
358
359 if (ui1 != ui2) {
360 if (flags & CMP_NOCASE) {
361 if (_RWSTD_UCHAR_MAX < ui1 || _RWSTD_UCHAR_MAX < ui2) {
362 ret = ui1 < ui2 ? -1 : +1;
363 break;
364 }
365 else if (_rw_upper [ui1] != _rw_upper [ui2]) {
366 ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
367 break;
368 }
369 }
370 else {
371 ret = ui1 < ui2 ? -1 : +1;
372 break;
373 }
374 }
375 }
376
377 if (CMP_RETOFF & flags) {
378 ret = ret ? int (inx) : -1;
379 }
380
381 return ret;
382
383#else // if !defined (_RWSTD_UINT32_T)
384
385 return _rw_cmpx (buf1, buf2, nelems, 4, flags);
386
387#endif // _RWSTD_UINT32_T
388}
389
390
391// compares two arrays of objects each 64 bits in size
392static int
393_rw_cmp8 (const void *buf1,
394 const void *buf2,
395 size_t nelems,
396 int flags = 0)
397{
398#ifdef _RWSTD_UINT64_T
399
400 typedef _RWSTD_UINT64_T UI64T;
401
402 size_t inx = 0;
403 int ret = 0;
404
405 const UI64T *pi1 = _RWSTD_STATIC_CAST (const UI64T*, buf1);
406 const UI64T *pi2 = _RWSTD_STATIC_CAST (const UI64T*, buf2);
407
408 for (; nelems; ++pi1, ++pi2, ++inx) {
409
410 const UI64T ui1 = *pi1;
411 const UI64T ui2 = *pi2;
412
413 if (flags & CMP_NULTERM) {
414
415 if (0 == ui1) {
416 ret = ui2 ? -1 : 0;
417 break;
418 }
419
420 if (0 == ui2) {
421 ret = +1;
422 break;
423 }
424 }
425
426 if (ui1 != ui2) {
427 if (flags & CMP_NOCASE) {
428 if (_RWSTD_UCHAR_MAX < ui1 || _RWSTD_UCHAR_MAX < ui2) {
429 ret = ui1 < ui2 ? -1 : +1;
430 break;
431 }
432 else if (_rw_upper [ui1] != _rw_upper [ui2]) {
433 ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
434 break;
435 }
436 }
437 else {
438 ret = ui1 < ui2 ? -1 : +1;
439 break;
440 }
441 }
442 }
443
444 if (CMP_RETOFF & flags) {
445 ret = ret ? int (inx) : -1;
446 }
447
448 return ret;
449
450#else // if !defined (_RWSTD_UINT64_T)
451
452 return _rw_cmpx (buf1, buf2, nelems, 8, flags);
453
454#endif // _RWSTD_UINT64_T
455}
456
457
458// compares two arrays of objects of unequal size
459static int
460_rw_cmpxx (const void* buf1,
461 const void* buf2,
462 size_t nelems,
463 size_t size1,
464 size_t size2,
465 int flags)
466{
467 size_t inx = 0;
468 int ret = 0;
469
470 for (; inx < nelems; ++inx) {
471
472#ifdef _RWSTD_UINT64_T
473
474 _RWSTD_UINT64_T ui1;
475 _RWSTD_UINT64_T ui2;
476
477#else // if !defined (_RWSTD_UINT64_T)
478
479 size_t ui1;
480 size_t ui2;
481
482#endif // _RWSTD_UINT64_T
483
484 switch (size1) {
485
486#ifdef _RWSTD_UINT8_T
487
488 case 1: {
489 const _RWSTD_UINT8_T* ptr =
490 _RWSTD_STATIC_CAST (const _RWSTD_UINT8_T*, buf1);
491 ui1 = *ptr++;
492 buf1 = ptr;
493 break;
494 }
495
496#endif // _RWSTD_UINT8_T
497
498#ifdef _RWSTD_UINT16_T
499
500 case 2: {
501 const _RWSTD_UINT16_T* ptr =
502 _RWSTD_STATIC_CAST (const _RWSTD_UINT16_T*, buf1);
503 ui1 = *ptr++;
504 buf1 = ptr;
505 break;
506 }
507
508#endif // _RWSTD_UINT16_T
509
510#ifdef _RWSTD_UINT32_T
511
512 case 4: {
513 const _RWSTD_UINT32_T* ptr =
514 _RWSTD_STATIC_CAST (const _RWSTD_UINT32_T*, buf1);
515 ui1 = *ptr++;
516 buf1 = ptr;
517 break;
518 }
519
520#endif // _RWSTD_UINT32_T
521
522#ifdef _RWSTD_UINT64_T
523
524 case 8: {
525 const _RWSTD_UINT64_T* ptr =
526 _RWSTD_STATIC_CAST (const _RWSTD_UINT64_T*, buf1);
527 ui1 = *ptr++;
528 buf1 = ptr;
529 break;
530 }
531
532#endif // _RWSTD_UINT64_T
533
534 default:
535 fprintf (stderr,
536 "%s:%d: comparison of objects %u and %u bytes in size "
537 "not implemented\n", __FILE__, __LINE__,
538 unsigned (size1), unsigned (size2));
539 abort ();
540 }
541
542 switch (size2) {
543
544#ifdef _RWSTD_UINT8_T
545
546 case 1: {
547 const _RWSTD_UINT8_T* ptr =
548 _RWSTD_STATIC_CAST (const _RWSTD_UINT8_T*, buf2);
549 ui2 = *ptr++;
550 buf2 = ptr;
551 break;
552 }
553
554#endif // _RWSTD_UINT8_T
555
556#ifdef _RWSTD_UINT16_T
557
558 case 2: {
559 const _RWSTD_UINT16_T* ptr =
560 _RWSTD_STATIC_CAST (const _RWSTD_UINT16_T*, buf2);
561 ui2 = *ptr++;
562 buf2 = ptr;
563 break;
564 }
565
566#endif // _RWSTD_UINT16_T
567
568#ifdef _RWSTD_UINT32_T
569
570 case 4: {
571 const _RWSTD_UINT32_T* ptr =
572 _RWSTD_STATIC_CAST (const _RWSTD_UINT32_T*, buf2);
573 ui2 = *ptr++;
574 buf2 = ptr;
575 break;
576 }
577
578#endif // _RWSTD_UINT32_T
579
580#ifdef _RWSTD_UINT64_T
581
582 case 8: {
583 const _RWSTD_UINT64_T* ptr =
584 _RWSTD_STATIC_CAST (const _RWSTD_UINT64_T*, buf2);
585 ui2 = *ptr++;
586 buf2 = ptr;
587 break;
588 }
589
590#endif // _RWSTD_UINT64_T
591
592 default:
593 fprintf (stderr,
594 "%s:%d: comparison of objects %u and %u bytes in size "
595 "not implemented\n", __FILE__, __LINE__,
596 unsigned (size1), unsigned (size2));
597 abort ();
598 }
599
600 if (flags & CMP_NULTERM) {
601
602 if (0 == ui1) {
603 ret = ui2 ? -1 : 0;
604 break;
605 }
606
607 if (0 == ui2) {
608 ret = +1;
609 break;
610 }
611 }
612
613 if (ui1 != ui2) {
614 if (flags & CMP_NOCASE) {
615 if (_RWSTD_UCHAR_MAX < ui1 || _RWSTD_UCHAR_MAX < ui2) {
616 ret = ui1 < ui2 ? -1 : +1;
617 break;
618 }
619 else if (_rw_upper [ui1] != _rw_upper [ui2]) {
620 ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
621 break;
622 }
623 }
624 else {
625 ret = ui1 < ui2 ? -1 : +1;
626 break;
627 }
628 }
629 }
630
631 if (CMP_RETOFF & flags) {
632 ret = ret ? int (inx) : -1;
633 }
634
635 return ret;
636}
637
638
639_TEST_EXPORT int
640rw_valcmp (const void* buf1,
641 const void* buf2,
642 size_t nelems,
643 size_t size1,
644 size_t size2,
645 int flags /* = 0 */)
646{
647 if (size1 == size2) {
648
649 switch (size1) {
650 case 1: return _rw_cmp1 (buf1, buf2, nelems, flags);
651 case 2: return _rw_cmp2 (buf1, buf2, nelems, flags);
652 case 4: return _rw_cmp4 (buf1, buf2, nelems, flags);
653 case 8: return _rw_cmp8 (buf1, buf2, nelems, flags);
654 }
655
656 return _rw_cmpx (buf1, buf2, nelems, size1, flags);
657 }
658
659 return _rw_cmpxx (buf1, buf2, nelems, size1, size2, flags);
660}
661
662
663_TEST_EXPORT int
664rw_strncmp (const char* str1,
665 const char* str2,
666 size_t nelems /* = _RWSTD_SIZE_MAX */,
667 int flags /* = CMP_NULTERM */)
668{
669 return rw_valcmp (str1, str2, nelems, 1, 1, flags);
670}
671
672
673#ifndef _RWSTD_NO_WCHAR_T
674
675_TEST_EXPORT int
676rw_strncmp (const char* str1,
677 const wchar_t* str2,
678 size_t nelems /* = _RWSTD_SIZE_MAX */,
679 int flags /* = CMP_NULTERM */)
680{
681 return rw_valcmp (str1, str2, nelems, 1, sizeof (wchar_t), flags);
682}
683
684
685_TEST_EXPORT int
686rw_strncmp (const wchar_t* str1,
687 const char* str2,
688 size_t nelems /* = _RWSTD_SIZE_MAX */,
689 int flags /* = CMP_NULTERM */)
690{
691 return rw_valcmp (str1, str2, nelems, sizeof (wchar_t), 1, flags);
692}
693
694
695_TEST_EXPORT int
696rw_strncmp (const wchar_t* str1,
697 const wchar_t* str2,
698 size_t nelems /* = _RWSTD_SIZE_MAX */,
699 int flags /* = CMP_NULTERM */)
700{
701 return rw_valcmp (str1, str2, nelems,
702 sizeof (wchar_t), sizeof (wchar_t), flags);
703}
704
705#endif // _RWSTD_NO_WCHAR_T
706
707
708// floating point comparison helpers based on
709// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
710
711_TEST_EXPORT int
712rw_fltcmp (float x, float y)
713{
714#if _RWSTD_FLT_SIZE == _RWSTD_SHRT_SIZE
715 typedef short IntT;
716 const IntT imin = _RWSTD_SHRT_MIN;
717#elif _RWSTD_FLT_SIZE == _RWSTD_INT_SIZE
718 typedef int IntT;
719 const IntT imin = _RWSTD_INT_MIN;
720#elif _RWSTD_FLT_SIZE == _RWSTD_LONG_SIZE
721 typedef long IntT;
722 const IntT imin = _RWSTD_LONG_MIN;
723#elif _RWSTD_FLT_SIZE == _RWSTD_LLONG_SIZE
724 typedef _RWSTD_LONG_LONG IntT;
725 const IntT imin = _RWSTD_LLONG_MIN;
726#else
727 // ???
728# error no integral type of the same size as float exists
729#endif
730
731 if (x == y)
732 return 0;
733
734 // make both arguments lexicographically ordered as twos-complement ints
735 IntT x_int = *(IntT*)&x;
736 if (x_int < 0)
737 x_int = imin - x_int;
738
739 IntT y_int = *(IntT*)&y;
740 if (y_int < 0)
741 y_int = imin - y_int;
742
743 const IntT int_diff = x_int - y_int;
744
745 return int_diff;
746}
747
748
749#define Abs(x) ((x) < 0 ? -(x) : (x))
750
751
752_TEST_EXPORT int
753rw_dblcmp (double x, double y)
754{
755#if _RWSTD_DBL_SIZE == _RWSTD_INT_SIZE
756 typedef int IntT;
757 const IntT imin = _RWSTD_INT_MIN;
758#elif _RWSTD_DBL_SIZE == _RWSTD_LONG_SIZE
759 typedef long IntT;
760 const IntT imin = _RWSTD_LONG_MIN;
761#elif _RWSTD_DBL_SIZE == _RWSTD_LLONG_SIZE
762 typedef _RWSTD_LONG_LONG IntT;
763 const IntT imin = _RWSTD_LLONG_MIN;
764#endif
765
766#if _RWSTD_LLONG_SIZE < _RWSTD_DBL_SIZE
767
768 if (x == y)
769 return 0;
770
771 // FIXME: use integer math as in the functions above
772
773 const double diff = x - y;
774
775 // check absolute error
776 if (Abs (diff) < _RWSTD_DBL_EPSILON)
777 return 0;
778
779 // check relative error
780 const double relerr =
781 Abs (x) < Abs (y) ? Abs (diff / y) : Abs (diff / x);
782
783 if (relerr <= 0.0000001)
784 return 0;
785
786 return x < y ? -1 : +1;
787
788#else // if !(_RWSTD_LLONG_SIZE < _RWSTD_DBL_SIZE)
789
790 if (x == y)
791 return 0;
792
793 IntT x_int = *(IntT*)&x;
794 if (x_int < 0)
795 x_int = imin - x_int;
796
797 IntT y_int = *(IntT*)&y;
798 if (y_int < 0)
799 y_int = imin - y_int;
800
801 const IntT int_diff = x_int - y_int;
802
803 // cast a possibly wider type to int to avoid compiler warnings
804 // this should be safe since the function should not be used to
805 // compare numbers that are that far apart
806 return int (int_diff);
807
808#endif // _RWSTD_LLONG_SIZE < _RWSTD_DBL_SIZE
809
810}
811
812
813#ifndef _RWSTD_NO_LONG_DOUBLE
814
815_TEST_EXPORT int
816rw_ldblcmp (long double x, long double y)
817{
818 if (sizeof (long double) == sizeof (double))
819 return rw_dblcmp (double (x), double (y));
820
821 if (x == y)
822 return 0;
823
824 // FIXME: use integer math as in the functions above
825
826 const long double diff = x - y;
827
828 // check absolute error
829 if (Abs (diff) < _RWSTD_LDBL_EPSILON)
830 return 0;
831
832 // check relative error
833 const long double relerr =
834 Abs (x) < Abs (y) ? Abs (diff / y) : Abs (diff / x);
835
836 if (relerr <= 0.0000001L)
837 return 0;
838
839 return x < y ? -1 : +1;
840}
841
842#endif // _RWSTD_NO_LONG_DOUBLE
#define i
Definition 17.names.cpp:126
#define y
Definition 17.names.cpp:141
#define ptr
Definition 17.names.cpp:525
#define x
Definition 17.names.cpp:140
#define p2
Definition 17.names.cpp:265
#define buf
Definition 17.names.cpp:452
#define inx
Definition 17.names.cpp:484
#define p1
Definition 17.names.cpp:239
#define flags
#define _RWSTD_LONG_LONG
#define stderr
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
#define _TEST_EXPORT
Definition rw_testdefs.h:55
#define CMP_NOCASE
Definition rw_valcmp.h:37
#define CMP_NULTERM
Definition rw_valcmp.h:35
#define CMP_RETOFF
Definition rw_valcmp.h:36
unsigned char UChar
Definition collate.cpp:122
_TEST_EXPORT int rw_valcmp(const void *buf1, const void *buf2, size_t nelems, size_t size1, size_t size2, int flags)
Definition valcmp.cpp:640
unsigned char UChar
Definition valcmp.cpp:38
_TEST_EXPORT int rw_strncmp(const char *str1, const char *str2, size_t nelems, int flags)
Definition valcmp.cpp:664
#define Abs(x)
Definition valcmp.cpp:749
_TEST_EXPORT int rw_fltcmp(float x, float y)
Definition valcmp.cpp:712
_TEST_EXPORT int rw_ldblcmp(long double x, long double y)
Definition valcmp.cpp:816
_TEST_EXPORT int rw_dblcmp(double x, double y)
Definition valcmp.cpp:753