strconv.odin 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. using import "core:decimal.odin"
  2. Int_Flag :: enum {
  3. Prefix = 1<<0,
  4. Plus = 1<<1,
  5. Space = 1<<2,
  6. }
  7. parse_bool :: proc(s: string) -> (result: bool = false, ok: bool) {
  8. switch s {
  9. case "1", "t", "T", "true", "TRUE", "True":
  10. return true, true;
  11. case "0", "f", "F", "false", "FALSE", "False":
  12. return false, true;
  13. }
  14. return;
  15. }
  16. _digit_value :: proc(r: rune) -> int {
  17. ri := int(r);
  18. v: int = 16;
  19. switch r {
  20. case '0'...'9': v = ri-'0';
  21. case 'a'...'z': v = ri-'a'+10;
  22. case 'A'...'Z': v = ri-'A'+10;
  23. }
  24. return v;
  25. }
  26. parse_i64 :: proc(s: string) -> i64 {
  27. neg := false;
  28. if len(s) > 1 {
  29. switch s[0] {
  30. case '-':
  31. neg = true;
  32. s = s[1..];
  33. case '+':
  34. s = s[1..];
  35. }
  36. }
  37. base: i64 = 10;
  38. if len(s) > 2 && s[0] == '0' {
  39. switch s[1] {
  40. case 'b': base = 2; s = s[2..];
  41. case 'o': base = 8; s = s[2..];
  42. case 'd': base = 10; s = s[2..];
  43. case 'z': base = 12; s = s[2..];
  44. case 'x': base = 16; s = s[2..];
  45. }
  46. }
  47. value: i64;
  48. for r in s {
  49. if r == '_' {
  50. continue;
  51. }
  52. v := i64(_digit_value(r));
  53. if v >= base {
  54. break;
  55. }
  56. value *= base;
  57. value += v;
  58. }
  59. if neg do return -value;
  60. return value;
  61. }
  62. parse_u64 :: proc(s: string) -> u64 {
  63. neg := false;
  64. if len(s) > 1 && s[0] == '+' {
  65. s = s[1..];
  66. }
  67. base := u64(10);
  68. if len(s) > 2 && s[0] == '0' {
  69. switch s[1] {
  70. case 'b': base = 2; s = s[2..];
  71. case 'o': base = 8; s = s[2..];
  72. case 'd': base = 10; s = s[2..];
  73. case 'z': base = 12; s = s[2..];
  74. case 'x': base = 16; s = s[2..];
  75. }
  76. }
  77. value: u64;
  78. for r in s {
  79. if r == '_' do continue;
  80. v := u64(_digit_value(r));
  81. if v >= base do break;
  82. value *= base;
  83. value += u64(v);
  84. }
  85. if neg do return -value;
  86. return value;
  87. }
  88. parse_int :: proc(s: string) -> int {
  89. return int(parse_i64(s));
  90. }
  91. parse_uint :: proc(s: string, base: int) -> uint {
  92. return uint(parse_u64(s));
  93. }
  94. parse_f32 :: proc(s: string) -> f32 {
  95. return f32(parse_f64(s));
  96. }
  97. parse_f64 :: proc(s: string) -> f64 {
  98. if s == "" {
  99. return 0;
  100. }
  101. i := 0;
  102. sign: f64 = 1;
  103. switch s[i] {
  104. case '-': i += 1; sign = -1;
  105. case '+': i += 1;
  106. }
  107. value: f64 = 0;
  108. for ; i < len(s); i += 1 {
  109. r := rune(s[i]);
  110. if r == '_' do continue;
  111. v := _digit_value(r);
  112. if v >= 10 do break;
  113. value *= 10;
  114. value += f64(v);
  115. }
  116. if i < len(s) && s[i] == '.' {
  117. pow10: f64 = 10;
  118. i += 1;
  119. for ; i < len(s); i += 1 {
  120. r := rune(s[i]);
  121. if r == '_' do continue;
  122. v := _digit_value(r);
  123. if v >= 10 do break;
  124. value += f64(v)/pow10;
  125. pow10 *= 10;
  126. }
  127. }
  128. frac := false;
  129. scale: f64 = 1;
  130. if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
  131. i += 1;
  132. if i < len(s) {
  133. switch s[i] {
  134. case '-': i += 1; frac = true;
  135. case '+': i += 1;
  136. }
  137. exp: u32 = 0;
  138. for ; i < len(s); i += 1 {
  139. r := rune(s[i]);
  140. if r == '_' do continue;
  141. d := u32(_digit_value(r));
  142. if d >= 10 do break;
  143. exp = exp * 10 + d;
  144. }
  145. if exp > 308 { exp = 308; }
  146. for exp >= 50 { scale *= 1e50; exp -= 50; }
  147. for exp >= 8 { scale *= 1e8; exp -= 8; }
  148. for exp > 0 { scale *= 10; exp -= 1; }
  149. }
  150. }
  151. if frac do return sign * (value/scale);
  152. return sign * (value*scale);
  153. }
  154. append_bool :: proc(buf: []byte, b: bool) -> string {
  155. n := 0;
  156. if b do n = copy(buf, cast([]byte)"true");
  157. else do n = copy(buf, cast([]byte)"false");
  158. return string(buf[..n]);
  159. }
  160. append_uint :: proc(buf: []byte, u: u64, base: int) -> string {
  161. return append_bits(buf, u64(u), base, false, 8*size_of(uint), digits, 0);
  162. }
  163. append_int :: proc(buf: []byte, i: i64, base: int) -> string {
  164. return append_bits(buf, u64(i), base, true, 8*size_of(int), digits, 0);
  165. }
  166. itoa :: proc(buf: []byte, i: int) -> string do return append_int(buf, i64(i), 10);
  167. append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string {
  168. return string(generic_ftoa(buf, f, fmt, prec, bit_size));
  169. }
  170. DecimalSlice :: struct {
  171. digits: []byte,
  172. count: int,
  173. decimal_point: int,
  174. neg: bool,
  175. }
  176. FloatInfo :: struct {
  177. mantbits: uint,
  178. expbits: uint,
  179. bias: int,
  180. }
  181. _f16_info := FloatInfo{10, 5, -15};
  182. _f32_info := FloatInfo{23, 8, -127};
  183. _f64_info := FloatInfo{52, 11, -1023};
  184. generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> []byte {
  185. bits: u64;
  186. flt: ^FloatInfo;
  187. switch bit_size {
  188. case 32:
  189. bits = u64(transmute(u32)f32(val));
  190. flt = &_f32_info;
  191. case 64:
  192. bits = transmute(u64)val;
  193. flt = &_f64_info;
  194. case:
  195. panic("strconv: invalid bit_size");
  196. }
  197. neg := bits>>(flt.expbits+flt.mantbits) != 0;
  198. exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1);
  199. mant := bits & (u64(1) << flt.mantbits - 1);
  200. switch exp {
  201. case 1<<flt.expbits - 1:
  202. s: string;
  203. if mant != 0 {
  204. s = "NaN";
  205. } else if neg {
  206. s = "-Inf";
  207. } else {
  208. s = "+Inf";
  209. }
  210. n := copy(buf, cast([]byte)s);
  211. return buf[..n];
  212. case 0: // denormalized
  213. exp += 1;
  214. case:
  215. mant |= u64(1) << flt.mantbits;
  216. }
  217. exp += flt.bias;
  218. d_: Decimal;
  219. d := &d_;
  220. assign(d, mant);
  221. shift(d, exp - int(flt.mantbits));
  222. digs: DecimalSlice;
  223. shortest := prec < 0;
  224. if shortest {
  225. round_shortest(d, mant, exp, flt);
  226. digs = DecimalSlice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
  227. switch fmt {
  228. case 'e', 'E': prec = digs.count-1;
  229. case 'f', 'F': prec = max(digs.count-digs.decimal_point, 0);
  230. case 'g', 'G': prec = digs.count;
  231. }
  232. } else {
  233. switch fmt {
  234. case 'e', 'E': round(d, prec+1);
  235. case 'f', 'F': round(d, d.decimal_point+prec);
  236. case 'g', 'G':
  237. if prec == 0 {
  238. prec = 1;
  239. }
  240. round(d, prec);
  241. }
  242. digs = DecimalSlice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
  243. }
  244. return format_digits(buf, shortest, neg, digs, prec, fmt);
  245. }
  246. format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: DecimalSlice, prec: int, fmt: byte) -> []byte {
  247. Buffer :: struct {
  248. b: []byte,
  249. n: int,
  250. }
  251. to_bytes :: proc(b: Buffer) -> []byte do return b.b[..b.n];
  252. add_bytes :: proc(buf: ^Buffer, bytes: ...byte) {
  253. buf.n += copy(buf.b[buf.n..], bytes);
  254. }
  255. b := Buffer{b = buf};
  256. switch fmt {
  257. case 'f', 'F':
  258. add_bytes(&b, neg ? '-' : '+');
  259. // integer, padded with zeros when needed
  260. if digs.decimal_point > 0 {
  261. m := min(digs.count, digs.decimal_point);
  262. add_bytes(&b, ...digs.digits[0..m]);
  263. for ; m < digs.decimal_point; m += 1 {
  264. add_bytes(&b, '0');
  265. }
  266. } else {
  267. add_bytes(&b, '0');
  268. }
  269. // fractional part
  270. if prec > 0 {
  271. add_bytes(&b, '.');
  272. for i in 0..prec {
  273. c: byte = '0';
  274. if j := digs.decimal_point + i; 0 <= j && j < digs.count {
  275. c = digs.digits[j];
  276. }
  277. add_bytes(&b, c);
  278. }
  279. }
  280. return to_bytes(b);
  281. case 'e', 'E':
  282. panic("strconv: e/E float printing is not yet supported");
  283. return to_bytes(b); // TODO
  284. case 'g', 'G':
  285. panic("strconv: g/G float printing is not yet supported");
  286. return to_bytes(b); // TODO
  287. case:
  288. add_bytes(&b, '%', fmt);
  289. return to_bytes(b);
  290. }
  291. }
  292. round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^FloatInfo) {
  293. if mant == 0 { // If mantissa is zero, the number is zero
  294. d.count = 0;
  295. return;
  296. }
  297. /*
  298. 10^(dp-nd) > 2^(exp-mantbits)
  299. log2(10) * (dp-nd) > exp-mantbits
  300. log(2) >~ 0.332
  301. 332*(dp-nd) >= 100*(exp-mantbits)
  302. */
  303. minexp := flt.bias+1;
  304. if exp > minexp && 332*(d.decimal_point-d.count) >= 100*(exp - int(flt.mantbits)) {
  305. // Number is already its shortest
  306. return;
  307. }
  308. upper_: Decimal; upper := &upper_;
  309. assign(upper, 2*mant - 1);
  310. shift(upper, exp - int(flt.mantbits) - 1);
  311. mantlo: u64;
  312. explo: int;
  313. if mant > 1<<flt.mantbits || exp == minexp {
  314. mantlo = mant-1;
  315. explo = exp;
  316. } else {
  317. mantlo = 2*mant - 1;
  318. explo = exp-1;
  319. }
  320. lower_: Decimal; lower := &lower_;
  321. assign(lower, 2*mantlo + 1);
  322. shift(lower, explo - int(flt.mantbits) - 1);
  323. inclusive := mant%2 == 0;
  324. for i in 0..d.count {
  325. l: byte = '0'; // lower digit
  326. if i < lower.count {
  327. l = lower.digits[i];
  328. }
  329. m := d.digits[i]; // middle digit
  330. u: byte = '0'; // upper digit
  331. if i < upper.count {
  332. u = upper.digits[i];
  333. }
  334. ok_round_down := l != m || inclusive && i+1 == lower.count;
  335. ok_round_up := m != u && (inclusive || m+1 < u || i+1 < upper.count);
  336. if ok_round_down && ok_round_up {
  337. round(d, i+1);
  338. return;
  339. }
  340. if ok_round_down {
  341. round_down(d, i+1);
  342. return;
  343. }
  344. if ok_round_up {
  345. round_up(d, i+1);
  346. return;
  347. }
  348. }
  349. }
  350. MAX_BASE :: 32;
  351. digits := "0123456789abcdefghijklmnopqrstuvwxyz";
  352. is_integer_negative :: proc(u: u64, is_signed: bool, bit_size: int) -> (unsigned: u64, neg: bool) {
  353. if is_signed {
  354. switch bit_size {
  355. case 8:
  356. i := i8(u);
  357. neg = i < 0;
  358. u = u64(abs(i));
  359. case 16:
  360. i := i16(u);
  361. neg = i < 0;
  362. u = u64(abs(i));
  363. case 32:
  364. i := i32(u);
  365. neg = i < 0;
  366. u = u64(abs(i));
  367. case 64:
  368. i := i64(u);
  369. neg = i < 0;
  370. u = u64(abs(i));
  371. case:
  372. panic("is_integer_negative: Unknown integer size");
  373. }
  374. }
  375. return u, neg;
  376. }
  377. append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flag) -> string {
  378. if base < 2 || base > MAX_BASE {
  379. panic("strconv: illegal base passed to append_bits");
  380. }
  381. neg: bool;
  382. a: [129]byte;
  383. i := len(a);
  384. u, neg = is_integer_negative(u, is_signed, bit_size);
  385. b := u64(base);
  386. for u >= b {
  387. i-=1; a[i] = digits[u % b];
  388. u /= b;
  389. }
  390. i-=1; a[i] = digits[u % b];
  391. if flags&Int_Flag.Prefix != 0 {
  392. ok := true;
  393. switch base {
  394. case 2: i-=1; a[i] = 'b';
  395. case 8: i-=1; a[i] = 'o';
  396. case 10: i-=1; a[i] = 'd';
  397. case 12: i-=1; a[i] = 'z';
  398. case 16: i-=1; a[i] = 'x';
  399. case: ok = false;
  400. }
  401. if ok {
  402. i-=1; a[i] = '0';
  403. }
  404. }
  405. switch {
  406. case neg:
  407. i-=1; a[i] = '-';
  408. case flags&Int_Flag.Plus != 0:
  409. i-=1; a[i] = '+';
  410. case flags&Int_Flag.Space != 0:
  411. i-=1; a[i] = ' ';
  412. }
  413. out := a[i..];
  414. copy(buf, out);
  415. return string(buf[0..len(out)]);
  416. }