*: update all clients of the `CString::to_s` services
[nit.git] / lib / core / fixed_ints.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
9 # another product.
10
11 # Basic integers of fixed-precision
12 #
13 # All classes defined here have C-equivalents and the semantics of their
14 # operations are the same as C's
15 #
16 # * Int8 => int8_t
17 # * Int16 => int16_t
18 # * UInt16 => uint16_t
19 # * Int32 => int32_t
20 # * UInt32 => uint32_t
21 #
22 # NOTE: No UInt8 is provided as Byte is the same
23 # SEE: kernel::Byte
24 #
25 # HOW TO USE:
26 # All classes can be instanciated via a literal rule.
27 # Namely, a suffix to append after the literal integer.
28 #
29 # * Int8 => i8
30 # * Byte => u8
31 # * Int16 => i16
32 # * UInt16 => u16
33 # * Int32 => i32
34 # * UInt32 => u32
35 module fixed_ints
36
37 import text
38
39 in "C" `{
40 #include <inttypes.h>
41 `}
42
43 redef class Numeric
44
45 # The Int8 equivalent of `self`
46 #
47 # assert (-1).to_i8 == 0xFFFFi8
48 # assert (1.9).to_i8 == 1i8
49 fun to_i8: Int8 do return self.to_i.to_i8
50
51 # The Int16 equivalent of `self`
52 #
53 # assert (-1).to_i16 == 0xFFFFi16
54 # assert (1.9).to_i16 == 1i16
55 fun to_i16: Int16 do return self.to_i.to_i16
56
57 # The UInt16 equivalent of `self`
58 #
59 # assert (-1).to_u16 == 0xFFFFu16
60 # assert (1.9).to_u16 == 1u16
61 fun to_u16: UInt16 do return self.to_i.to_u16
62
63 # The Int32 equivalent of `self`
64 #
65 # assert (-1).to_i32 == 0xFFFFFFFFi32
66 # assert (1.9).to_i32 == 1i32
67 fun to_i32: Int32 do return self.to_i.to_i32
68
69 # The UInt32 equivalent of `self`
70 #
71 # assert (-1).to_u32 == 0xFFFFFFFFu32
72 # assert (1.9).to_u32 == 1u32
73 fun to_u32: UInt32 do return self.to_i.to_u32
74
75 end
76
77 redef class Float
78 redef fun to_i8 is intern
79 redef fun to_i16 is intern
80 redef fun to_u16 is intern
81 redef fun to_i32 is intern
82 redef fun to_u32 is intern
83 end
84
85 redef class Byte
86 redef fun to_i8 is intern
87 redef fun to_i16 is intern
88 redef fun to_u16 is intern
89 redef fun to_i32 is intern
90 redef fun to_u32 is intern
91 end
92
93 redef class Int
94 redef fun to_i8 is intern
95 redef fun to_i16 is intern
96 redef fun to_u16 is intern
97 redef fun to_i32 is intern
98 redef fun to_u32 is intern
99 end
100
101 # Native 8-bit signed integer.
102 # Same as a C `int8_t`
103 universal Int8
104 super Discrete
105 super Numeric
106
107 redef type OTHER: Int8
108
109 redef fun successor(i) do return self + i.to_i8
110 redef fun predecessor(i) do return self - i.to_i8
111
112 redef fun object_id is intern
113 redef fun hash do return self.to_i
114 redef fun ==(i) is intern
115 redef fun !=(i) is intern
116 redef fun output is intern
117
118 redef fun <=(i) is intern
119 redef fun <(i) is intern
120 redef fun >=(i) is intern
121 redef fun >(i) is intern
122 redef fun +(i) is intern
123
124 # assert -1i8 == 0xFFi8
125 # assert -0i8 == 0x00i8
126 redef fun - is intern
127 redef fun -(i) is intern
128 redef fun *(i) is intern
129 redef fun /(i) is intern
130
131 # Modulo of `self` with `i`.
132 #
133 # Returns the remainder of division of `self` by `i`.
134 #
135 # assert 5i8 % 2i8 == 1i8
136 # assert 10i8 % 2i8 == 0i8
137 fun %(i: Int8): Int8 is intern
138
139 redef fun zero do return 0.to_i8
140 redef fun value_of(val) do return val.to_i8
141
142 # `i` bits shift to the left
143 #
144 # assert 5i8 << 1 == 10i8
145 fun <<(i: Int): Int8 is intern
146
147 # `i` bits shift to the right
148 #
149 # assert 5i8 >> 1 == 2i8
150 fun >>(i: Int): Int8 is intern
151
152 redef fun to_i is intern
153 redef fun to_f is intern
154 redef fun to_b is intern
155 redef fun to_i8 do return self
156 redef fun to_i16 is intern
157 redef fun to_u16 is intern
158 redef fun to_i32 is intern
159 redef fun to_u32 is intern
160
161 # Returns `self` as a Char according to its ASCII value.
162 fun ascii: Char `{ return (uint32_t)self; `}
163
164 redef fun distance(i) do return (self - i).to_i
165
166 redef fun <=>(other)
167 do
168 if self < other then
169 return -1
170 else if other < self then
171 return 1
172 else
173 return 0
174 end
175 end
176
177 redef fun is_between(c, d)
178 do
179 if self < c or d < self then
180 return false
181 else
182 return true
183 end
184 end
185
186 redef fun max(other)
187 do
188 if self < other then
189 return other
190 else
191 return self
192 end
193 end
194
195 redef fun min(c)
196 do
197 if c < self then
198 return c
199 else
200 return self
201 end
202 end
203
204 # Returns the result of a binary AND operation on `self` and `i`
205 #
206 # assert 0x10i8 & 0x01i8 == 0i8
207 fun &(i: Int8): Int8 is intern
208
209 # Returns the result of a binary OR operation on `self` and `i`
210 #
211 # assert 0x10i8 | 0x01i8 == 0x11i8
212 fun |(i: Int8): Int8 is intern
213
214 # Returns the result of a binary XOR operation on `self` and `i`
215 #
216 # assert 0x101i8 ^ 0x110i8 == 0x11i8
217 fun ^(i: Int8): Int8 is intern
218
219 # Returns the 1's complement of `self`
220 #
221 # assert ~0x2Fi8 == 0xD0i8
222 fun ~: Int8 is intern
223
224 # C function to calculate the length of the `CString` to receive `self`
225 private fun to_s_len: Int `{
226 return snprintf(NULL, 0, "%"PRIi8, self);
227 `}
228
229 # C function to convert a nit Int to a CString (char*)
230 private fun native_to_s(nstr: CString, strlen: Int) `{
231 snprintf(nstr, strlen, "%"PRIi8, self);
232 `}
233
234 # Displayable Int8
235 #
236 # assert 1i8.to_s == "1"
237 # assert (-123i8).to_s == "-123"
238 redef fun to_s do
239 var nslen = to_s_len
240 var ns = new CString(nslen + 1)
241 ns[nslen] = 0u8
242 native_to_s(ns, nslen + 1)
243 return ns.to_s_unsafe(nslen, copy=false)
244 end
245 end
246
247 # Native 16-bit signed integer.
248 # Same as a C `int16_t`
249 universal Int16
250 super Discrete
251 super Numeric
252
253 redef type OTHER: Int16
254
255 redef fun successor(i) do return self + i.to_i16
256 redef fun predecessor(i) do return self - i.to_i16
257
258 redef fun object_id is intern
259 redef fun hash do return self.to_i
260 redef fun ==(i) is intern
261 redef fun !=(i) is intern
262 redef fun output is intern
263
264 redef fun <=(i) is intern
265 redef fun <(i) is intern
266 redef fun >=(i) is intern
267 redef fun >(i) is intern
268 redef fun +(i) is intern
269
270 # assert -1i16 == 0xFFFFi16
271 # assert -0i16 == 0i16
272 redef fun - is intern
273 redef fun -(i) is intern
274 redef fun *(i) is intern
275 redef fun /(i) is intern
276
277 # Returns `self` as a Char according to its ASCII value.
278 fun ascii: Char `{ return (uint32_t)self; `}
279
280 # Modulo of `self` with `i`.
281 #
282 # Returns the remainder of division of `self` by `i`.
283 #
284 # assert 5i16 % 2i16 == 1i16
285 # assert 10i16 % 2i16 == 0i16
286 fun %(i: Int16): Int16 is intern
287
288 redef fun zero do return 0.to_i16
289 redef fun value_of(val) do return val.to_i16
290
291 # `i` bits shift to the left
292 #
293 # assert 5i16 << 1 == 10i16
294 fun <<(i: Int): Int16 is intern
295
296 # `i` bits shift to the right
297 #
298 # assert 5i16 >> 1 == 2i16
299 fun >>(i: Int): Int16 is intern
300
301 redef fun to_i is intern
302 redef fun to_f is intern
303 redef fun to_b is intern
304 redef fun to_i8 is intern
305 redef fun to_i16 do return self
306 redef fun to_u16 is intern
307 redef fun to_i32 is intern
308 redef fun to_u32 is intern
309
310 redef fun distance(i) do return (self - i).to_i
311
312 redef fun <=>(other)
313 do
314 if self < other then
315 return -1
316 else if other < self then
317 return 1
318 else
319 return 0
320 end
321 end
322
323 redef fun is_between(c, d)
324 do
325 if self < c or d < self then
326 return false
327 else
328 return true
329 end
330 end
331
332 redef fun max(other)
333 do
334 if self < other then
335 return other
336 else
337 return self
338 end
339 end
340
341 redef fun min(c)
342 do
343 if c < self then
344 return c
345 else
346 return self
347 end
348 end
349
350 # Returns the result of a binary AND operation on `self` and `i`
351 #
352 # assert 0x10i16 & 0x01i16 == 0i16
353 fun &(i: Int16): Int16 is intern
354
355 # Returns the result of a binary OR operation on `self` and `i`
356 #
357 # assert 0x10i16 | 0x01i16 == 0x11i16
358 fun |(i: Int16): Int16 is intern
359
360 # Returns the result of a binary XOR operation on `self` and `i`
361 #
362 # assert 0x101i16 ^ 0x110i16 == 0x11i16
363 fun ^(i: Int16): Int16 is intern
364
365 # Returns the 1's complement of `self`
366 #
367 # assert ~0x2Fi16 == 0xFFD0i16
368 fun ~: Int16 is intern
369
370 # C function to calculate the length of the `CString` to receive `self`
371 private fun to_s_len: Int `{
372 return snprintf(NULL, 0, "%"PRIi16, self);
373 `}
374
375 # C function to convert a nit Int to a CString (char*)
376 private fun native_to_s(nstr: CString, strlen: Int) `{
377 snprintf(nstr, strlen, "%"PRIi16, self);
378 `}
379
380 # Displayable Int16
381 #
382 # assert 1i16.to_s == "1"
383 # assert (-123i16).to_s == "-123"
384 redef fun to_s do
385 var nslen = to_s_len
386 var ns = new CString(nslen + 1)
387 ns[nslen] = 0u8
388 native_to_s(ns, nslen + 1)
389 return ns.to_s_unsafe(nslen, copy=false)
390 end
391 end
392
393 # Native 16-bit unsigned integer.
394 # Same as a C `uint16_t`
395 universal UInt16
396 super Discrete
397 super Numeric
398
399 redef type OTHER: UInt16
400
401 redef fun successor(i) do return self + i.to_u16
402 redef fun predecessor(i) do return self - i.to_u16
403
404 redef fun object_id is intern
405 redef fun hash do return self.to_i
406 redef fun ==(i) is intern
407 redef fun !=(i) is intern
408 redef fun output is intern
409
410 redef fun <=(i) is intern
411 redef fun <(i) is intern
412 redef fun >=(i) is intern
413 redef fun >(i) is intern
414 redef fun +(i) is intern
415
416 # assert -1u16 == 0xFFFFu16
417 # assert -0u16 == 0u16
418 redef fun - is intern
419 redef fun -(i) is intern
420 redef fun *(i) is intern
421 redef fun /(i) is intern
422
423 # Modulo of `self` with `i`.
424 #
425 # Returns the remainder of division of `self` by `i`.
426 #
427 # assert 5u16 % 2u16 == 1u16
428 # assert 10u16 % 2u16 == 0u16
429 fun %(i: UInt16): UInt16 is intern
430
431 redef fun zero do return 0.to_u16
432 redef fun value_of(val) do return val.to_u16
433
434 # Returns `self` as a Char according to its ASCII value.
435 fun ascii: Char `{ return (uint32_t)self; `}
436
437 # `i` bits shift to the left
438 #
439 # assert 5u16 << 1 == 10u16
440 fun <<(i: Int): UInt16 is intern
441
442 # `i` bits shift to the right
443 #
444 # assert 5u16 >> 1 == 2u16
445 fun >>(i: Int): UInt16 is intern
446
447 redef fun to_i is intern
448 redef fun to_f is intern
449 redef fun to_b is intern
450 redef fun to_i8 is intern
451 redef fun to_i16 is intern
452 redef fun to_u16 do return self
453 redef fun to_i32 is intern
454 redef fun to_u32 is intern
455
456 redef fun distance(i) do return (self - i).to_i
457
458 redef fun <=>(other)
459 do
460 if self < other then
461 return -1
462 else if other < self then
463 return 1
464 else
465 return 0
466 end
467 end
468
469 redef fun is_between(c, d)
470 do
471 if self < c or d < self then
472 return false
473 else
474 return true
475 end
476 end
477
478 redef fun max(other)
479 do
480 if self < other then
481 return other
482 else
483 return self
484 end
485 end
486
487 redef fun min(c)
488 do
489 if c < self then
490 return c
491 else
492 return self
493 end
494 end
495
496 # Returns the result of a binary AND operation on `self` and `i`
497 #
498 # assert 0x10u16 & 0x01u16 == 0u16
499 fun &(i: UInt16): UInt16 is intern
500
501 # Returns the result of a binary OR operation on `self` and `i`
502 #
503 # assert 0x10u16 | 0x01u16 == 0x11u16
504 fun |(i: UInt16): UInt16 is intern
505
506 # Returns the result of a binary XOR operation on `self` and `i`
507 #
508 # assert 0x101u16 ^ 0x110u16 == 0x11u16
509 fun ^(i: UInt16): UInt16 is intern
510
511 # Returns the 1's complement of `self`
512 #
513 # assert ~0x2Fu16 == 0xFFD0u16
514 fun ~: UInt16 is intern
515
516 # C function to calculate the length of the `CString` to receive `self`
517 private fun to_s_len: Int `{
518 return snprintf(NULL, 0, "%"PRIu16, self);
519 `}
520
521 # C function to convert a nit Int to a CString (char*)
522 private fun native_to_s(nstr: CString, strlen: Int) `{
523 snprintf(nstr, strlen, "%"PRIu16, self);
524 `}
525
526 # Displayable UInt16
527 #
528 # assert 1u16.to_s == "1"
529 # assert (-123u16).to_s == "65413"
530 redef fun to_s do
531 var nslen = to_s_len
532 var ns = new CString(nslen + 1)
533 ns[nslen] = 0u8
534 native_to_s(ns, nslen + 1)
535 return ns.to_s_unsafe(nslen, copy=false)
536 end
537 end
538
539
540 # Native 32-bit signed integer.
541 # Same as a C `int32_t`
542 universal Int32
543 super Discrete
544 super Numeric
545
546 redef type OTHER: Int32
547
548 redef fun successor(i) do return self + i.to_i32
549 redef fun predecessor(i) do return self - i.to_i32
550
551 redef fun object_id is intern
552 redef fun hash do return self.to_i
553 redef fun ==(i) is intern
554 redef fun !=(i) is intern
555 redef fun output is intern
556
557 redef fun <=(i) is intern
558 redef fun <(i) is intern
559 redef fun >=(i) is intern
560 redef fun >(i) is intern
561 redef fun +(i) is intern
562
563 # assert -1i32 == 0xFFFFFFFFi32
564 # assert -0i32 == 0x00i32
565 redef fun - is intern
566 redef fun -(i) is intern
567 redef fun *(i) is intern
568 redef fun /(i) is intern
569
570 # Returns `self` as a Char according to its ASCII value.
571 fun ascii: Char `{ return (uint32_t)self; `}
572
573 # Modulo of `self` with `i`.
574 #
575 # Returns the remainder of division of `self` by `i`.
576 #
577 # assert 5i32 % 2i32 == 1i32
578 # assert 10i32 % 2i32 == 0i32
579 fun %(i: Int32): Int32 is intern
580
581 redef fun zero do return 0.to_i32
582 redef fun value_of(val) do return val.to_i32
583
584 # `i` bits shift to the left
585 #
586 # assert 5i32 << 1 == 10i32
587 fun <<(i: Int): Int32 is intern
588
589 # `i` bits shift to the right
590 #
591 # assert 5i32 >> 1 == 2i32
592 fun >>(i: Int): Int32 is intern
593
594 redef fun to_i is intern
595 redef fun to_f is intern
596 redef fun to_b is intern
597 redef fun to_i8 is intern
598 redef fun to_i16 is intern
599 redef fun to_u16 is intern
600 redef fun to_i32 do return self
601 redef fun to_u32 is intern
602
603 redef fun distance(i) do return (self - i).to_i
604
605 redef fun <=>(other)
606 do
607 if self < other then
608 return -1
609 else if other < self then
610 return 1
611 else
612 return 0
613 end
614 end
615
616 redef fun is_between(c, d)
617 do
618 if self < c or d < self then
619 return false
620 else
621 return true
622 end
623 end
624
625 redef fun max(other)
626 do
627 if self < other then
628 return other
629 else
630 return self
631 end
632 end
633
634 redef fun min(c)
635 do
636 if c < self then
637 return c
638 else
639 return self
640 end
641 end
642
643 # Returns the result of a binary AND operation on `self` and `i`
644 #
645 # assert 0x10i32 & 0x01i32 == 0i32
646 fun &(i: Int32): Int32 is intern
647
648 # Returns the result of a binary OR operation on `self` and `i`
649 #
650 # assert 0x10i32 | 0x01i32 == 0x11i32
651 fun |(i: Int32): Int32 is intern
652
653 # Returns the result of a binary XOR operation on `self` and `i`
654 #
655 # assert 0x101i32 ^ 0x110i32 == 0x11i32
656 fun ^(i: Int32): Int32 is intern
657
658 # Returns the 1's complement of `self`
659 #
660 # assert ~0x2Fi32 == 0xFFFFFFD0i32
661 fun ~: Int32 is intern
662
663 # C function to calculate the length of the `CString` to receive `self`
664 private fun to_s_len: Int `{
665 return snprintf(NULL, 0, "%"PRIi32, self);
666 `}
667
668 # C function to convert a nit Int to a CString (char*)
669 private fun native_to_s(nstr: CString, strlen: Int) `{
670 snprintf(nstr, strlen, "%"PRIi32, self);
671 `}
672
673 # Displayable Int32
674 #
675 # assert 1i32.to_s == "1"
676 # assert (-123i32).to_s == "-123"
677 redef fun to_s do
678 var nslen = to_s_len
679 var ns = new CString(nslen + 1)
680 ns[nslen] = 0u8
681 native_to_s(ns, nslen + 1)
682 return ns.to_s_unsafe(nslen, copy=false)
683 end
684 end
685
686 # Native 32-bit unsigned integer.
687 # Same as a C `uint32_t`
688 universal UInt32
689 super Discrete
690 super Numeric
691
692 redef type OTHER: UInt32
693
694 redef fun successor(i) do return self + i.to_u32
695 redef fun predecessor(i) do return self - i.to_u32
696
697 redef fun object_id is intern
698 redef fun hash do return self.to_i
699 redef fun ==(i) is intern
700 redef fun !=(i) is intern
701 redef fun output is intern
702
703 redef fun <=(i) is intern
704 redef fun <(i) is intern
705 redef fun >=(i) is intern
706 redef fun >(i) is intern
707 redef fun +(i) is intern
708
709 # assert -1u32 == 0xFFFFFFFFu32
710 # assert -0u32 == 0x00u32
711 redef fun - is intern
712 redef fun -(i) is intern
713 redef fun *(i) is intern
714 redef fun /(i) is intern
715
716 # Returns `self` as a Char according to its ASCII value.
717 fun ascii: Char `{ return (uint32_t)self; `}
718
719 # Modulo of `self` with `i`.
720 #
721 # Returns the remainder of division of `self` by `i`.
722 #
723 # assert 5u32 % 2u32 == 1u32
724 # assert 10u32 % 2u32 == 0u32
725 fun %(i: UInt32): UInt32 is intern
726
727 redef fun zero do return 0.to_u32
728 redef fun value_of(val) do return val.to_u32
729
730 # `i` bits shift to the left
731 #
732 # assert 5u32 << 1 == 10u32
733 fun <<(i: Int): UInt32 is intern
734
735 # `i` bits shift to the right
736 #
737 # assert 5u32 >> 1 == 2u32
738 fun >>(i: Int): UInt32 is intern
739
740 redef fun to_i is intern
741 redef fun to_f is intern
742 redef fun to_b is intern
743 redef fun to_i8 is intern
744 redef fun to_i16 is intern
745 redef fun to_u16 is intern
746 redef fun to_i32 is intern
747 redef fun to_u32 do return self
748
749 redef fun distance(i) do return (self - i).to_i
750
751 redef fun <=>(other)
752 do
753 if self < other then
754 return -1
755 else if other < self then
756 return 1
757 else
758 return 0
759 end
760 end
761
762 redef fun is_between(c, d)
763 do
764 if self < c or d < self then
765 return false
766 else
767 return true
768 end
769 end
770
771 redef fun max(other)
772 do
773 if self < other then
774 return other
775 else
776 return self
777 end
778 end
779
780 redef fun min(c)
781 do
782 if c < self then
783 return c
784 else
785 return self
786 end
787 end
788
789 # Returns the result of a binary AND operation on `self` and `i`
790 #
791 # assert 0x10u32 & 0x01u32 == 0u32
792 fun &(i: UInt32): UInt32 is intern
793
794 # Returns the result of a binary OR operation on `self` and `i`
795 #
796 # assert 0x10u32 | 0x01u32 == 0x11u32
797 fun |(i: UInt32): UInt32 is intern
798
799 # Returns the result of a binary XOR operation on `self` and `i`
800 #
801 # assert 0x101u32 ^ 0x110u32 == 0x11u32
802 fun ^(i: UInt32): UInt32 is intern
803
804 # Returns the 1's complement of `self`
805 #
806 # assert ~0x2Fu32 == 0xFFFFFFD0u32
807 fun ~: UInt32 is intern
808
809 # C function to calculate the length of the `CString` to receive `self`
810 private fun to_s_len: Int `{
811 return snprintf(NULL, 0, "%"PRIu32, self);
812 `}
813
814 # C function to convert a nit Int to a CString (char*)
815 private fun native_to_s(nstr: CString, strlen: Int) `{
816 snprintf(nstr, strlen, "%"PRIu32, self);
817 `}
818
819 # Displayable UInt32
820 #
821 # assert 1u32.to_s == "1"
822 # assert (-123u32).to_s == "4294967173"
823 redef fun to_s do
824 var nslen = to_s_len
825 var ns = new CString(nslen + 1)
826 ns[nslen] = 0u8
827 native_to_s(ns, nslen + 1)
828 return ns.to_s_unsafe(nslen, copy=false)
829 end
830 end
831
832 redef class Text
833
834 # Removes the numeric head of `self` if present
835 #
836 # intrude import core::fixed_ints
837 # assert "0xFFEF".strip_numhead == "FFEF"
838 # assert "0o7364".strip_numhead == "7364"
839 # assert "0b01001".strip_numhead == "01001"
840 # assert "98".strip_numhead == "98"
841 private fun strip_numhead: Text do
842 if get_numhead != "" then return substring_from(2)
843 return self
844 end
845
846 # Gets the numeric head of `self` if present
847 # Returns "" otherwise
848 #
849 # intrude import core::fixed_ints
850 # assert "0xFEFF".get_numhead == "0x"
851 # assert "0b01001".get_numhead == "0b"
852 # assert "0o872".get_numhead == "0o"
853 # assert "98".get_numhead == ""
854 private fun get_numhead: Text do
855 if self.length < 2 then return ""
856 var c = self[0]
857 if c != '0' then return ""
858 c = self[1]
859 if c == 'x' or c == 'b' or c == 'o' or
860 c == 'X' or c == 'B' or c == 'O' then return substring(0, 2)
861 return ""
862 end
863
864 # Removes the numeric extension if present
865 #
866 # intrude import core::fixed_ints
867 # assert "0xFEFFu8".strip_numext == "0xFEFF"
868 # assert "0b01001u8".strip_numext == "0b01001"
869 # assert "0o872u8".strip_numext == "0o872"
870 # assert "98".strip_numext == "98"
871 private fun strip_numext: Text do
872 var ext = get_numext
873 if ext != "" then return substring(0, length - ext.length)
874 return self
875 end
876
877 # Gets the numeric extension (i/u 8/16/32) in `self` is present
878 # Returns "" otherwise
879 #
880 # intrude import core::fixed_ints
881 # assert "0xFEFFu8".get_numext == "u8"
882 # assert "0b01001u8".get_numext == "u8"
883 # assert "0o872u8".get_numext == "u8"
884 # assert "98".get_numext == ""
885 private fun get_numext: Text do
886 var len = self.length
887 var max = if self.length < 3 then self.length else 3
888 for i in [1 .. max] do
889 var c = self[len - i]
890 if c == 'i' or c == 'u' then return substring_from(len - i)
891 end
892 return ""
893 end
894
895 # Is `self` a well-formed Integer (i.e. parsable via `to_i`)
896 #
897 # assert "123".is_int
898 # assert "0b1011".is_int
899 # assert not "0x_".is_int
900 # assert not "0xGE".is_int
901 # assert not "".is_int
902 # assert not "Not an Int".is_int
903 # assert not "-".is_int
904 fun is_int: Bool do
905 if byte_length == 0 then return false
906 var s = remove_all('_')
907 var pos = 0
908 var len = s.length
909 while pos < len and s[pos] == '-' do
910 pos += 1
911 end
912 s = s.substring_from(pos)
913 var rets = s.strip_numhead
914 if rets == "" then return false
915 var hd = get_numhead
916 if hd == "0x" or hd == "0X" then return rets.is_hex
917 if hd == "0b" or hd == "0B" then return rets.is_bin
918 if hd == "0o" or hd == "0O" then return rets.is_oct
919 return rets.is_dec
920 end
921
922 redef fun to_i
923 do
924 assert self.is_int
925 var s = remove_all('_')
926 var val = 0
927 var neg = false
928 var pos = 0
929 while s[pos] == '-' do
930 neg = not neg
931 pos += 1
932 end
933 s = s.substring_from(pos)
934 if s.length >= 2 then
935 var s1 = s[1]
936 if s1 == 'x' or s1 == 'X' then
937 val = s.substring_from(2).to_hex
938 else if s1 == 'o' or s1 == 'O' then
939 val = s.substring_from(2).to_oct
940 else if s1 == 'b' or s1 == 'B' then
941 val = s.substring_from(2).to_bin
942 else if s1.is_numeric then
943 val = s.to_dec
944 end
945 else
946 val = s.to_dec
947 end
948 return if neg then -val else val
949 end
950
951 # Is `self` a valid integer ?
952 #
953 # assert "0xFE46u8".is_num
954 # assert "0b0100".is_num
955 # assert "0o645".is_num
956 # assert "897u8".is_num
957 fun is_num: Bool do
958 var prefix = get_numhead
959 var s = strip_numhead.strip_numext.remove_all('_')
960 if prefix != "" then
961 var c = prefix[1]
962 if c == 'x' or c == 'X' then return s.is_hex
963 if c == 'o' or c == 'O' then return s.is_oct
964 if c == 'b' or c == 'B' then return s.is_bin
965 end
966 return s.is_dec
967 end
968
969 # If `self` is a properly formatted integer, returns the corresponding value
970 # Returns `null` otherwise
971 #
972 # assert "0xFEu8".to_num == 254u8
973 # assert "0b10_10".to_num != 10u8
974 fun to_num: nullable Numeric do
975 if not is_num then return null
976 var s = remove_all('_')
977 var ext = s.get_numext
978 var trunk = s.strip_numext
979 if trunk.strip_numhead == "" then return null
980 var trval = trunk.to_i
981 if ext == "u8" then
982 return trval.to_b
983 else if ext == "i8" then
984 return trval.to_i8
985 else if ext == "i16" then
986 return trval.to_i16
987 else if ext == "u16" then
988 return trval.to_u16
989 else if ext == "i32" then
990 return trval.to_i32
991 else if ext == "u32" then
992 return trval.to_u32
993 else if ext == "" then
994 return trval
995 else
996 return null
997 end
998 end
999 end