fmt.odin 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. import (
  2. "os.odin";
  3. "mem.odin";
  4. "utf8.odin";
  5. "types.odin";
  6. "strconv.odin";
  7. "raw.odin";
  8. )
  9. _BUFFER_SIZE :: 1<<12;
  10. StringBuffer :: union {
  11. []u8,
  12. [dynamic]u8,
  13. }
  14. FmtInfo :: struct {
  15. minus: bool;
  16. plus: bool;
  17. space: bool;
  18. zero: bool;
  19. hash: bool;
  20. width_set: bool;
  21. prec_set: bool;
  22. width: int;
  23. prec: int;
  24. indent: int;
  25. reordered: bool;
  26. good_arg_index: bool;
  27. buf: ^StringBuffer;
  28. arg: any; // Temporary
  29. }
  30. string_buffer_data :: proc(buf: ^StringBuffer) -> []u8 {
  31. match b in buf {
  32. case []u8: return b[..];
  33. case [dynamic]u8: return b[..];
  34. }
  35. return nil;
  36. }
  37. string_buffer_data :: proc(buf: StringBuffer) -> []u8 {
  38. match b in buf {
  39. case []u8: return b[..];
  40. case [dynamic]u8: return b[..];
  41. }
  42. return nil;
  43. }
  44. to_string :: proc(buf: StringBuffer) -> string {
  45. return string(string_buffer_data(buf));
  46. }
  47. write_string :: proc(buf: ^StringBuffer, s: string) {
  48. write_bytes(buf, cast([]u8)s);
  49. }
  50. write_bytes :: proc(buf: ^StringBuffer, data: []u8) {
  51. match b in buf {
  52. case []u8: append(b, ...data);
  53. case [dynamic]u8: append(b, ...data);
  54. }
  55. }
  56. write_byte :: proc(buf: ^StringBuffer, data: u8) {
  57. match b in buf {
  58. case []u8: append(b, data);
  59. case [dynamic]u8: append(b, data);
  60. }
  61. }
  62. write_rune :: proc(buf: ^StringBuffer, r: rune) {
  63. if r < utf8.RUNE_SELF {
  64. write_byte(buf, u8(r));
  65. return;
  66. }
  67. b, n := utf8.encode_rune(r);
  68. write_bytes(buf, b[..n]);
  69. }
  70. write_int :: proc(buf: ^StringBuffer, i: i128, base: int) {
  71. b: [129]u8;
  72. s := strconv.append_bits(b[..0], u128(i), base, true, 128, strconv.digits, 0);
  73. write_string(buf, s);
  74. }
  75. write_int :: proc(buf: ^StringBuffer, i: i64, base: int) {
  76. b: [129]u8;
  77. s := strconv.append_bits(b[..0], u128(i), base, true, 64, strconv.digits, 0);
  78. write_string(buf, s);
  79. }
  80. fprint :: proc(fd: os.Handle, args: ...any) -> int {
  81. data: [_BUFFER_SIZE]u8;
  82. buf := StringBuffer(data[..0]);
  83. sbprint(&buf, ...args);
  84. res := string_buffer_data(buf);
  85. os.write(fd, res);
  86. return len(res);
  87. }
  88. fprintln :: proc(fd: os.Handle, args: ...any) -> int {
  89. data: [_BUFFER_SIZE]u8;
  90. buf := StringBuffer(data[..0]);
  91. sbprintln(&buf, ...args);
  92. res := string_buffer_data(buf);
  93. os.write(fd, res);
  94. return len(res);
  95. }
  96. fprintf :: proc(fd: os.Handle, fmt: string, args: ...any) -> int {
  97. data: [_BUFFER_SIZE]u8;
  98. buf := StringBuffer(data[..0]);
  99. sbprintf(&buf, fmt, ...args);
  100. res := string_buffer_data(buf);
  101. os.write(fd, res);
  102. return len(res);
  103. }
  104. // print* procedures return the number of bytes written
  105. print :: proc(args: ...any) -> int { return fprint(os.stdout, ...args); }
  106. print_err :: proc(args: ...any) -> int { return fprint(os.stderr, ...args); }
  107. println :: proc(args: ...any) -> int { return fprintln(os.stdout, ...args); }
  108. println_err :: proc(args: ...any) -> int { return fprintln(os.stderr, ...args); }
  109. printf :: proc(fmt: string, args: ...any) -> int { return fprintf(os.stdout, fmt, ...args); }
  110. printf_err :: proc(fmt: string, args: ...any) -> int { return fprintf(os.stderr, fmt, ...args); }
  111. // aprint* procedures return a string that was allocated with the current context
  112. // They must be freed accordingly
  113. aprint :: proc(args: ...any) -> string {
  114. buf := StringBuffer(make([dynamic]u8));
  115. sbprint(&buf, ...args);
  116. return to_string(buf);
  117. }
  118. aprintln :: proc(args: ...any) -> string {
  119. buf := StringBuffer(make([dynamic]u8));
  120. sbprintln(&buf, ...args);
  121. return to_string(buf);
  122. }
  123. aprintf :: proc(fmt: string, args: ...any) -> string {
  124. buf := StringBuffer(make([dynamic]u8));
  125. sbprintf(&buf, fmt, ...args);
  126. return to_string(buf);
  127. }
  128. // bprint* procedures return a string using a buffer from an array
  129. bprint :: proc(buf: []u8, args: ...any) -> string {
  130. sb := StringBuffer(buf[..0..len(buf)]);
  131. return sbprint(&sb, ...args);
  132. }
  133. bprintln :: proc(buf: []u8, args: ...any) -> string {
  134. sb := StringBuffer(buf[..0..len(buf)]);
  135. return sbprintln(&sb, ...args);
  136. }
  137. bprintf :: proc(buf: []u8, fmt: string, args: ...any) -> string {
  138. sb := StringBuffer(buf[..0..len(buf)]);
  139. return sbprintf(&sb, fmt, ...args);
  140. }
  141. fprint_type :: proc(fd: os.Handle, info: ^TypeInfo) {
  142. data: [_BUFFER_SIZE]u8;
  143. buf := StringBuffer(data[..0]);
  144. write_type(&buf, info);
  145. os.write(fd, string_buffer_data(buf));
  146. }
  147. write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
  148. if ti == nil do return;
  149. using TypeInfo;
  150. match info in ti.variant {
  151. case Named:
  152. write_string(buf, info.name);
  153. case Integer:
  154. match {
  155. case ti == type_info_of(int): write_string(buf, "int");
  156. case ti == type_info_of(uint): write_string(buf, "uint");
  157. case:
  158. if info.signed do write_byte(buf, 'i');
  159. else do write_byte(buf, 'u');
  160. write_int(buf, i64(8*ti.size), 10);
  161. }
  162. case Rune:
  163. write_string(buf, "rune");
  164. case Float:
  165. match ti.size {
  166. case 2: write_string(buf, "f16");
  167. case 4: write_string(buf, "f32");
  168. case 8: write_string(buf, "f64");
  169. }
  170. case Complex:
  171. match ti.size {
  172. case 4: write_string(buf, "complex32");
  173. case 8: write_string(buf, "complex64");
  174. case 16: write_string(buf, "complex128");
  175. }
  176. case String: write_string(buf, "string");
  177. case Boolean: write_string(buf, "bool");
  178. case Any:
  179. write_string(buf, "any");
  180. case Pointer:
  181. if info.elem == nil {
  182. write_string(buf, "rawptr");
  183. } else {
  184. write_string(buf, "^");
  185. write_type(buf, info.elem);
  186. }
  187. case Procedure:
  188. write_string(buf, "proc");
  189. if info.params == nil {
  190. write_string(buf, "()");
  191. } else {
  192. t := info.params.variant.(Tuple);
  193. write_string(buf, "(");
  194. for t, i in t.types {
  195. if i > 0 do write_string(buf, ", ");
  196. write_type(buf, t);
  197. }
  198. write_string(buf, ")");
  199. }
  200. if info.results != nil {
  201. write_string(buf, " -> ");
  202. write_type(buf, info.results);
  203. }
  204. case Tuple:
  205. count := len(info.names);
  206. if count != 1 do write_string(buf, "(");
  207. for name, i in info.names {
  208. if i > 0 do write_string(buf, ", ");
  209. t := info.types[i];
  210. if len(name) > 0 {
  211. write_string(buf, name);
  212. write_string(buf, ": ");
  213. }
  214. write_type(buf, t);
  215. }
  216. if count != 1 do write_string(buf, ")");
  217. case Array:
  218. write_string(buf, "[");
  219. fi := FmtInfo{buf = buf};
  220. write_int(buf, i64(info.count), 10);
  221. write_string(buf, "]");
  222. write_type(buf, info.elem);
  223. case DynamicArray:
  224. write_string(buf, "[dynamic]");
  225. write_type(buf, info.elem);
  226. case Slice:
  227. write_string(buf, "[]");
  228. write_type(buf, info.elem);
  229. case Vector:
  230. write_string(buf, "[vector ");
  231. write_int(buf, i64(info.count), 10);
  232. write_string(buf, "]");
  233. write_type(buf, info.elem);
  234. case Map:
  235. write_string(buf, "map[");
  236. write_type(buf, info.key);
  237. write_byte(buf, ']');
  238. write_type(buf, info.value);
  239. case Struct:
  240. write_string(buf, "struct ");
  241. if info.is_packed do write_string(buf, "#packed ");
  242. if info.is_ordered do write_string(buf, "#ordered ");
  243. if info.is_raw_union do write_string(buf, "#raw_union ");
  244. if info.custom_align {
  245. write_string(buf, "#align ");
  246. write_int(buf, i64(ti.align), 10);
  247. write_byte(buf, ' ');
  248. }
  249. write_byte(buf, '{');
  250. for name, i in info.names {
  251. if i > 0 do write_string(buf, ", ");
  252. write_string(buf, name);
  253. write_string(buf, ": ");
  254. write_type(buf, info.types[i]);
  255. }
  256. write_byte(buf, '}');
  257. case Union:
  258. write_string(buf, "union {");
  259. for variant, i in info.variants {
  260. if i > 0 do write_string(buf, ", ");
  261. write_type(buf, variant);
  262. }
  263. write_string(buf, "}");
  264. case Enum:
  265. write_string(buf, "enum ");
  266. write_type(buf, info.base);
  267. write_string(buf, " {");
  268. for name, i in info.names {
  269. if i > 0 do write_string(buf, ", ");
  270. write_string(buf, name);
  271. }
  272. write_string(buf, "}");
  273. case BitField:
  274. write_string(buf, "bit_field ");
  275. if ti.align != 1 {
  276. write_string(buf, "#align ");
  277. write_int(buf, i64(ti.align), 10);
  278. write_rune(buf, ' ');
  279. }
  280. write_string(buf, " {");
  281. for name, i in info.names {
  282. if i > 0 do write_string(buf, ", ");
  283. write_string(buf, name);
  284. write_string(buf, ": ");
  285. write_int(buf, i64(info.bits[i]), 10);
  286. }
  287. write_string(buf, "}");
  288. }
  289. }
  290. _parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: bool) {
  291. is_digit :: proc(r: rune) -> bool #inline {
  292. return '0' <= r && r <= '9';
  293. }
  294. result := 0;
  295. ok := true;
  296. i := 0;
  297. for i < len(s[offset..]) {
  298. c := rune(s[offset+i]);
  299. if !is_digit(c) do break;
  300. i += 1;
  301. result *= 10;
  302. result += int(c)-'0';
  303. }
  304. return result, offset+i, i != 0;
  305. }
  306. _arg_number :: proc(fi: ^FmtInfo, arg_index: int, format: string, offset, arg_count: int) -> (index, offset: int, ok: bool) {
  307. parse_arg_number :: proc(format: string) -> (int, int, bool) {
  308. if len(format) < 3 do return 0, 1, false;
  309. for i in 1...len(format) {
  310. if format[i] == ']' {
  311. width, new_index, ok := _parse_int(format, 1);
  312. if !ok || new_index != i {
  313. return 0, i+1, false;
  314. }
  315. return width-1, i+1, true;
  316. }
  317. }
  318. return 0, 1, false;
  319. }
  320. if len(format) <= offset || format[offset] != '[' {
  321. return arg_index, offset, false;
  322. }
  323. fi.reordered = true;
  324. index, width, ok := parse_arg_number(format[offset..]);
  325. if ok && 0 <= index && index < arg_count {
  326. return index, offset+width, true;
  327. }
  328. fi.good_arg_index = false;
  329. return arg_index, offset+width, false;
  330. }
  331. int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
  332. num := 0;
  333. new_arg_index := arg_index;
  334. ok := true;
  335. if arg_index < len(args) {
  336. arg := args[arg_index];
  337. arg.type_info = type_info_base(arg.type_info);
  338. match i in arg {
  339. case int: num = i;
  340. case i8: num = int(i);
  341. case i16: num = int(i);
  342. case i32: num = int(i);
  343. case i64: num = int(i);
  344. case u8: num = int(i);
  345. case u16: num = int(i);
  346. case u32: num = int(i);
  347. case u64: num = int(i);
  348. case:
  349. ok = false;
  350. }
  351. }
  352. return num, new_arg_index, ok;
  353. }
  354. fmt_bad_verb :: proc(using fi: ^FmtInfo, verb: rune) {
  355. assert(verb != 'v');
  356. write_string(buf, "%!");
  357. write_rune(buf, verb);
  358. write_byte(buf, '(');
  359. if arg.type_info != nil {
  360. write_type(buf, arg.type_info);
  361. write_byte(buf, '=');
  362. fmt_value(fi, arg, 'v');
  363. } else {
  364. write_string(buf, "<nil>");
  365. }
  366. write_byte(buf, ')');
  367. }
  368. fmt_bool :: proc(using fi: ^FmtInfo, b: bool, verb: rune) {
  369. match verb {
  370. case 't', 'v':
  371. s := "false";
  372. if b do s = "true";
  373. write_string(buf, s);
  374. case:
  375. fmt_bad_verb(fi, verb);
  376. }
  377. }
  378. fmt_write_padding :: proc(fi: ^FmtInfo, width: int) {
  379. if width <= 0 do return;
  380. pad_byte: u8 = '0';
  381. if fi.space do pad_byte = ' ';
  382. for _ in 0..width {
  383. write_byte(fi.buf, pad_byte);
  384. }
  385. }
  386. _fmt_int :: proc(fi: ^FmtInfo, u: u128, base: int, is_signed: bool, bit_size: int, digits: string) {
  387. _, neg := strconv.is_integer_negative(u128(u), is_signed, bit_size);
  388. BUF_SIZE :: 256;
  389. if fi.width_set || fi.prec_set {
  390. width := fi.width + fi.prec + 3; // 3 extra bytes for sign and prefix
  391. if width > BUF_SIZE {
  392. // TODO(bill):????
  393. panic("_fmt_int: buffer overrun. Width and precision too big");
  394. }
  395. }
  396. prec := 0;
  397. if fi.prec_set {
  398. prec = fi.prec;
  399. if prec == 0 && u == 0 {
  400. prev_zero := fi.zero;
  401. fi.zero = false;
  402. fmt_write_padding(fi, fi.width);
  403. fi.zero = prev_zero;
  404. return;
  405. }
  406. } else if fi.zero && fi.width_set {
  407. prec = fi.width;
  408. if neg || fi.plus || fi.space {
  409. // There needs to be space for the "sign"
  410. prec -= 1;
  411. }
  412. }
  413. match base {
  414. case 2, 8, 10, 12, 16:
  415. break;
  416. case:
  417. panic("_fmt_int: unknown base, whoops");
  418. }
  419. buf: [256]u8;
  420. start := 0;
  421. flags: strconv.IntFlag;
  422. if fi.hash && !fi.zero do flags |= strconv.IntFlag.Prefix;
  423. if fi.plus do flags |= strconv.IntFlag.Plus;
  424. if fi.space do flags |= strconv.IntFlag.Space;
  425. s := strconv.append_bits(buf[start..start], u128(u), base, is_signed, bit_size, digits, flags);
  426. if fi.hash && fi.zero {
  427. c: u8;
  428. match base {
  429. case 2: c = 'b';
  430. case 8: c = 'o';
  431. case 10: c = 'd';
  432. case 12: c = 'z';
  433. case 16: c = 'x';
  434. }
  435. if c != 0 {
  436. write_byte(fi.buf, '0');
  437. write_byte(fi.buf, c);
  438. }
  439. }
  440. prev_zero := fi.zero;
  441. defer fi.zero = prev_zero;
  442. fi.zero = false;
  443. _pad(fi, s);
  444. }
  445. __DIGITS_LOWER := "0123456789abcdefx";
  446. __DIGITS_UPPER := "0123456789ABCDEFX";
  447. fmt_rune :: proc(fi: ^FmtInfo, r: rune, verb: rune) {
  448. match verb {
  449. case 'c', 'r', 'v':
  450. write_rune(fi.buf, r);
  451. case:
  452. fmt_bad_verb(fi, verb);
  453. }
  454. }
  455. fmt_int :: proc(fi: ^FmtInfo, u: u128, is_signed: bool, bit_size: int, verb: rune) {
  456. match verb {
  457. case 'v': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
  458. case 'b': _fmt_int(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER);
  459. case 'o': _fmt_int(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER);
  460. case 'd': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
  461. case 'z': _fmt_int(fi, u, 12, is_signed, bit_size, __DIGITS_LOWER);
  462. case 'x': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_LOWER);
  463. case 'X': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_UPPER);
  464. case 'c', 'r':
  465. fmt_rune(fi, rune(u), verb);
  466. case 'U':
  467. r := rune(u);
  468. if r < 0 || r > utf8.MAX_RUNE {
  469. fmt_bad_verb(fi, verb);
  470. } else {
  471. write_string(fi.buf, "U+");
  472. _fmt_int(fi, u, 16, false, bit_size, __DIGITS_UPPER);
  473. }
  474. case:
  475. fmt_bad_verb(fi, verb);
  476. }
  477. }
  478. _pad :: proc(fi: ^FmtInfo, s: string) {
  479. if !fi.width_set {
  480. write_string(fi.buf, s);
  481. return;
  482. }
  483. width := fi.width - utf8.rune_count(s);
  484. if fi.minus { // right pad
  485. write_string(fi.buf, s);
  486. fmt_write_padding(fi, width);
  487. } else { // left pad
  488. fmt_write_padding(fi, width);
  489. write_string(fi.buf, s);
  490. }
  491. }
  492. fmt_float :: proc(fi: ^FmtInfo, v: f64, bit_size: int, verb: rune) {
  493. match verb {
  494. // case 'e', 'E', 'f', 'F', 'g', 'G', 'v':
  495. // case 'f', 'F', 'v':
  496. case 'f', 'F', 'v':
  497. prec: int = 3;
  498. if fi.prec_set do prec = fi.prec;
  499. buf: [386]u8;
  500. str := strconv.append_float(buf[1..1], v, 'f', prec, bit_size);
  501. str = string(buf[...len(str)]);
  502. if str[1] == '+' || str[1] == '-' {
  503. str = str[1..];
  504. } else {
  505. str[0] = '+';
  506. }
  507. if fi.space && !fi.plus && str[0] == '+' {
  508. str[0] = ' ';
  509. }
  510. if len(str) > 1 && str[1] == 'N' && str[1] == 'I' {
  511. write_string(fi.buf, str);
  512. return;
  513. }
  514. if fi.plus || str[0] != '+' {
  515. if fi.zero && fi.width_set && fi.width > len(str) {
  516. write_byte(fi.buf, str[0]);
  517. fmt_write_padding(fi, fi.width - len(str));
  518. write_string(fi.buf, str[1..]);
  519. } else {
  520. _pad(fi, str);
  521. }
  522. } else {
  523. _pad(fi, str[1..]);
  524. }
  525. case:
  526. fmt_bad_verb(fi, verb);
  527. }
  528. }
  529. fmt_string :: proc(fi: ^FmtInfo, s: string, verb: rune) {
  530. match verb {
  531. case 's', 'v':
  532. write_string(fi.buf, s);
  533. case 'x', 'X':
  534. space := fi.space;
  535. fi.space = false;
  536. defer fi.space = space;
  537. for i in 0..len(s) {
  538. if i > 0 && space do write_byte(fi.buf, ' ');
  539. char_set := __DIGITS_UPPER;
  540. if verb == 'x' do char_set = __DIGITS_LOWER;
  541. _fmt_int(fi, u128(s[i]), 16, false, 8, char_set);
  542. }
  543. case:
  544. fmt_bad_verb(fi, verb);
  545. }
  546. }
  547. fmt_pointer :: proc(fi: ^FmtInfo, p: rawptr, verb: rune) {
  548. match verb {
  549. case 'p', 'v':
  550. // Okay
  551. case:
  552. fmt_bad_verb(fi, verb);
  553. return;
  554. }
  555. u := u128(uint(p));
  556. if !fi.hash || verb == 'v' {
  557. write_string(fi.buf, "0x");
  558. }
  559. _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER);
  560. }
  561. enum_value_to_string :: proc(v: any) -> (string, bool) {
  562. v.type_info = type_info_base(v.type_info);
  563. using TypeInfo;
  564. match e in v.type_info.variant {
  565. case: return "", false;
  566. case Enum:
  567. get_str :: proc(i: $T, e: Enum) -> (string, bool) {
  568. if types.is_string(e.base) {
  569. for val, idx in e.values {
  570. if v, ok := val.(T); ok && v == i {
  571. return e.names[idx], true;
  572. }
  573. }
  574. } else if len(e.values) == 0 {
  575. return "", true;
  576. } else {
  577. for val, idx in e.values {
  578. if v, ok := val.(T); ok && v == i {
  579. return e.names[idx], true;
  580. }
  581. }
  582. }
  583. return "", false;
  584. }
  585. a := any{v.data, type_info_base(e.base)};
  586. match v in a {
  587. case rune: return get_str(v, e);
  588. case i8: return get_str(v, e);
  589. case i16: return get_str(v, e);
  590. case i32: return get_str(v, e);
  591. case i64: return get_str(v, e);
  592. case i128: return get_str(v, e);
  593. case int: return get_str(v, e);
  594. case u8: return get_str(v, e);
  595. case u16: return get_str(v, e);
  596. case u32: return get_str(v, e);
  597. case u64: return get_str(v, e);
  598. case u128: return get_str(v, e);
  599. case uint: return get_str(v, e);
  600. case f32: return get_str(v, e);
  601. case f64: return get_str(v, e);
  602. }
  603. }
  604. return "", false;
  605. }
  606. string_to_enum_value :: proc(T: type, s: string) -> (T, bool) {
  607. ti := type_info_base(type_info_of(T));
  608. if e, ok := ti.variant.(TypeInfo.Enum); ok {
  609. for str, idx in e.names {
  610. if s == str {
  611. // NOTE(bill): Unsafe cast
  612. ptr := cast(^T)&e.values[idx];
  613. return ptr^, true;
  614. }
  615. }
  616. }
  617. return T{}, false;
  618. }
  619. fmt_enum :: proc(fi: ^FmtInfo, v: any, verb: rune) {
  620. if v.type_info == nil || v.data == nil {
  621. write_string(fi.buf, "<nil>");
  622. return;
  623. }
  624. using TypeInfo;
  625. match e in v.type_info.variant {
  626. case: fmt_bad_verb(fi, verb);
  627. case Enum:
  628. match verb {
  629. case: fmt_bad_verb(fi, verb);
  630. case 'd', 'f':
  631. fmt_arg(fi, any{v.data, type_info_base(e.base)}, verb);
  632. case 's', 'v':
  633. str, ok := enum_value_to_string(v);
  634. if !ok do str = "!%(BAD ENUM VALUE)";
  635. write_string(fi.buf, str);
  636. }
  637. }
  638. }
  639. fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
  640. if v.data == nil || v.type_info == nil {
  641. write_string(fi.buf, "<nil>");
  642. return;
  643. }
  644. using TypeInfo;
  645. match info in v.type_info.variant {
  646. case Named:
  647. match b in info.base.variant {
  648. case Struct:
  649. if verb != 'v' {
  650. fmt_bad_verb(fi, verb);
  651. return;
  652. }
  653. if b.is_raw_union {
  654. write_string(fi.buf, info.name);
  655. write_string(fi.buf, "{}");
  656. return;
  657. }
  658. write_string(fi.buf, info.name);
  659. write_byte(fi.buf, '{');
  660. defer write_byte(fi.buf, '}');
  661. hash := fi.hash; defer fi.hash = hash;
  662. indent := fi.indent; defer fi.indent -= 1;
  663. fi.hash = false;
  664. fi.indent += 1;
  665. if hash do write_byte(fi.buf, '\n');
  666. for _, i in b.names {
  667. if !hash && i > 0 do write_string(fi.buf, ", ");
  668. if hash {
  669. for in 0..fi.indent {
  670. write_byte(fi.buf, '\t');
  671. }
  672. }
  673. write_string(fi.buf, b.names[i]);
  674. write_string(fi.buf, " = ");
  675. if t := b.types[i]; types.is_any(t) {
  676. write_string(fi.buf, "any{}");
  677. } else {
  678. data := cast(^u8)v.data + b.offsets[i];
  679. fmt_arg(fi, any{rawptr(data), t}, 'v');
  680. }
  681. if hash do write_string(fi.buf, ",\n");
  682. }
  683. case:
  684. fmt_value(fi, any{v.data, info.base}, verb);
  685. }
  686. case Boolean: fmt_arg(fi, v, verb);
  687. case Integer: fmt_arg(fi, v, verb);
  688. case Rune: fmt_arg(fi, v, verb);
  689. case Float: fmt_arg(fi, v, verb);
  690. case Complex: fmt_arg(fi, v, verb);
  691. case String: fmt_arg(fi, v, verb);
  692. case Pointer:
  693. if v.type_info == type_info_of(^TypeInfo) {
  694. write_type(fi.buf, (cast(^^TypeInfo)v.data)^);
  695. } else {
  696. fmt_pointer(fi, (cast(^rawptr)v.data)^, verb);
  697. }
  698. case Array:
  699. write_byte(fi.buf, '[');
  700. defer write_byte(fi.buf, ']');
  701. for i in 0..info.count {
  702. if i > 0 do write_string(fi.buf, ", ");
  703. data := cast(^u8)v.data + i*info.elem_size;
  704. fmt_arg(fi, any{rawptr(data), info.elem}, verb);
  705. }
  706. case DynamicArray:
  707. write_byte(fi.buf, '[');
  708. defer write_byte(fi.buf, ']');
  709. array := cast(^raw.DynamicArray)v.data;
  710. for i in 0..array.len {
  711. if i > 0 do write_string(fi.buf, ", ");
  712. data := cast(^u8)array.data + i*info.elem_size;
  713. fmt_arg(fi, any{rawptr(data), info.elem}, verb);
  714. }
  715. case Slice:
  716. write_byte(fi.buf, '[');
  717. defer write_byte(fi.buf, ']');
  718. slice := cast(^[]u8)v.data;
  719. for _, i in slice {
  720. if i > 0 do write_string(fi.buf, ", ");
  721. data := &slice[0] + i*info.elem_size;
  722. fmt_arg(fi, any{rawptr(data), info.elem}, verb);
  723. }
  724. case Vector:
  725. write_byte(fi.buf, '<');
  726. defer write_byte(fi.buf, '>');
  727. for i in 0..info.count {
  728. if i > 0 do write_string(fi.buf, ", ");
  729. data := cast(^u8)v.data + i*info.elem_size;
  730. fmt_value(fi, any{rawptr(data), info.elem}, verb);
  731. }
  732. case Map:
  733. if verb != 'v' {
  734. fmt_bad_verb(fi, verb);
  735. return;
  736. }
  737. write_string(fi.buf, "map[");
  738. defer write_byte(fi.buf, ']');
  739. entries := &((cast(^raw.DynamicMap)v.data).entries);
  740. gs := type_info_base(info.generated_struct).variant.(Struct);
  741. ed := type_info_base(gs.types[1]).variant.(DynamicArray);
  742. entry_type := ed.elem.variant.(Struct);
  743. entry_size := ed.elem_size;
  744. for i in 0..entries.len {
  745. if i > 0 do write_string(fi.buf, ", ");
  746. data := cast(^u8)entries.data + i*entry_size;
  747. header := cast(^__MapEntryHeader)data;
  748. if types.is_string(info.key) {
  749. write_string(fi.buf, header.key.str);
  750. } else {
  751. fi := FmtInfo{buf = fi.buf};
  752. fmt_arg(&fi, any{rawptr(&header.key.hash), info.key}, 'v');
  753. }
  754. write_string(fi.buf, "=");
  755. value := data + entry_type.offsets[2];
  756. fmt_arg(fi, any{rawptr(value), info.value}, 'v');
  757. }
  758. case Struct:
  759. if info.is_raw_union {
  760. write_string(fi.buf, "(raw_union)");
  761. return;
  762. }
  763. write_byte(fi.buf, '{');
  764. defer write_byte(fi.buf, '}');
  765. hash := fi.hash; defer fi.hash = hash;
  766. indent := fi.indent; defer fi.indent -= 1;
  767. fi.hash = false;
  768. fi.indent += 1;
  769. if hash do write_byte(fi.buf, '\n');
  770. for _, i in info.names {
  771. if !hash && i > 0 do write_string(fi.buf, ", ");
  772. if hash {
  773. for in 0..fi.indent {
  774. write_byte(fi.buf, '\t');
  775. }
  776. }
  777. write_string(fi.buf, info.names[i]);
  778. write_string(fi.buf, " = ");
  779. if t := info.types[i]; types.is_any(t) {
  780. write_string(fi.buf, "any{}");
  781. } else {
  782. data := cast(^u8)v.data + info.offsets[i];
  783. fmt_arg(fi, any{rawptr(data), t}, 'v');
  784. }
  785. if hash do write_string(fi.buf, ",\n");
  786. }
  787. case Union:
  788. data := cast(^u8)v.data;
  789. tipp := cast(^^TypeInfo)(data + info.tag_offset);
  790. if data == nil || tipp == nil {
  791. write_string(fi.buf, "(union)");
  792. } else {
  793. ti := tipp^;
  794. fmt_arg(fi, any{data, ti}, verb);
  795. }
  796. case Enum:
  797. fmt_enum(fi, v, verb);
  798. case Procedure:
  799. write_type(fi.buf, v.type_info);
  800. write_string(fi.buf, " @ ");
  801. fmt_pointer(fi, (cast(^rawptr)v.data)^, 'p');
  802. }
  803. }
  804. fmt_complex :: proc(fi: ^FmtInfo, c: complex128, bits: int, verb: rune) {
  805. match verb {
  806. case 'f', 'F', 'v':
  807. r, i := real(c), imag(c);
  808. fmt_float(fi, r, bits/2, verb);
  809. if !fi.plus && i >= 0 {
  810. write_rune(fi.buf, '+');
  811. }
  812. fmt_float(fi, i, bits/2, verb);
  813. write_rune(fi.buf, 'i');
  814. case:
  815. fmt_bad_verb(fi, verb);
  816. return;
  817. }
  818. }
  819. _u128_to_lo_hi :: proc(a: u128) -> (lo, hi: u64) { return u64(a), u64(a>>64); }
  820. _i128_to_lo_hi :: proc(a: u128) -> (lo: u64 hi: i64) { return u64(a), i64(a>>64); }
  821. do_foo :: proc(fi: ^FmtInfo, f: f64) {
  822. fmt_string(fi, "Hellope$%!", 'v');
  823. }
  824. fmt_arg :: proc(fi: ^FmtInfo, arg: any, verb: rune) {
  825. if arg == nil {
  826. write_string(fi.buf, "<nil>");
  827. return;
  828. }
  829. fi.arg = arg;
  830. if verb == 'T' {
  831. ti := arg.type_info;
  832. match a in arg {
  833. case ^TypeInfo: ti = a;
  834. }
  835. write_type(fi.buf, ti);
  836. return;
  837. }
  838. base_arg := arg;
  839. base_arg.type_info = type_info_base(base_arg.type_info);
  840. match a in base_arg {
  841. case any: fmt_arg(fi, a, verb);
  842. case bool: fmt_bool(fi, a, verb);
  843. case rune: fmt_rune(fi, a, verb);
  844. case f32: fmt_float(fi, f64(a), 32, verb);
  845. case f64: fmt_float(fi, a, 64, verb);
  846. case complex64: fmt_complex(fi, complex128(a), 64, verb);
  847. case complex128: fmt_complex(fi, a, 128, verb);
  848. case int: fmt_int(fi, u128(a), true, 8*size_of(int), verb);
  849. case i8: fmt_int(fi, u128(a), true, 8, verb);
  850. case i16: fmt_int(fi, u128(a), true, 16, verb);
  851. case i32: fmt_int(fi, u128(a), true, 32, verb);
  852. case i64: fmt_int(fi, u128(a), true, 64, verb);
  853. case i128: fmt_int(fi, u128(a), true, 128, verb);
  854. case uint: fmt_int(fi, u128(a), false, 8*size_of(uint), verb);
  855. case u8: fmt_int(fi, u128(a), false, 8, verb);
  856. case u16: fmt_int(fi, u128(a), false, 16, verb);
  857. case u32: fmt_int(fi, u128(a), false, 32, verb);
  858. case u64: fmt_int(fi, u128(a), false, 64, verb);
  859. case u128: fmt_int(fi, u128(a), false, 128, verb);
  860. case string: fmt_string(fi, a, verb);
  861. case: fmt_value(fi, arg, verb);
  862. }
  863. }
  864. sbprint :: proc(buf: ^StringBuffer, args: ...any) -> string {
  865. fi: FmtInfo;
  866. prev_string := false;
  867. fi.buf = buf;
  868. for arg, i in args {
  869. is_string := arg != nil && types.is_string(arg.type_info);
  870. if i > 0 && !is_string && !prev_string {
  871. write_byte(buf, ' ');
  872. }
  873. fmt_value(&fi, args[i], 'v');
  874. prev_string = is_string;
  875. }
  876. return to_string(buf^);
  877. }
  878. sbprintln :: proc(buf: ^StringBuffer, args: ...any) -> string {
  879. fi: FmtInfo;
  880. fi.buf = buf;
  881. for arg, i in args {
  882. if i > 0 do write_byte(buf, ' ');
  883. fmt_value(&fi, args[i], 'v');
  884. }
  885. write_byte(buf, '\n');
  886. return to_string(buf^);
  887. }
  888. sbprintf :: proc(b: ^StringBuffer, fmt: string, args: ...any) -> string {
  889. fi: FmtInfo;
  890. arg_index: int = 0;
  891. end := len(fmt);
  892. was_prev_index := false;
  893. for i := 0; i < end; /**/ {
  894. fi = FmtInfo{buf = b, good_arg_index = true};
  895. prev_i := i;
  896. for i < end && fmt[i] != '%' {
  897. i += 1;
  898. }
  899. if i > prev_i {
  900. write_string(b, fmt[prev_i..i]);
  901. }
  902. if i >= end {
  903. break;
  904. }
  905. // Process a "verb"
  906. i += 1;
  907. prefix_loop: for ; i < end; i += 1 {
  908. match fmt[i] {
  909. case '+':
  910. fi.plus = true;
  911. case '-':
  912. fi.minus = true;
  913. fi.zero = false;
  914. case ' ':
  915. fi.space = true;
  916. case '#':
  917. fi.hash = true;
  918. case '0':
  919. fi.zero = !fi.minus;
  920. case:
  921. break prefix_loop;
  922. }
  923. }
  924. arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
  925. // Width
  926. if i < end && fmt[i] == '*' {
  927. i += 1;
  928. fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index);
  929. if !fi.width_set {
  930. write_string(b, "%!(BAD WIDTH)");
  931. }
  932. if fi.width < 0 {
  933. fi.width = -fi.width;
  934. fi.minus = true;
  935. fi.zero = false;
  936. }
  937. was_prev_index = false;
  938. } else {
  939. fi.width, i, fi.width_set = _parse_int(fmt, i);
  940. if was_prev_index && fi.width_set { // %[6]2d
  941. fi.good_arg_index = false;
  942. }
  943. }
  944. // Precision
  945. if i < end && fmt[i] == '.' {
  946. i += 1;
  947. if was_prev_index { // %[6].2d
  948. fi.good_arg_index = false;
  949. }
  950. if i < end && fmt[i] == '*' {
  951. arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
  952. i += 1;
  953. fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index);
  954. if fi.prec < 0 {
  955. fi.prec = 0;
  956. fi.prec_set = false;
  957. }
  958. if !fi.prec_set {
  959. write_string(fi.buf, "%!(BAD PRECISION)");
  960. }
  961. was_prev_index = false;
  962. } else {
  963. fi.prec, i, fi.prec_set = _parse_int(fmt, i);
  964. if !fi.prec_set {
  965. // fi.prec_set = true;
  966. // fi.prec = 0;
  967. }
  968. }
  969. }
  970. if !was_prev_index {
  971. arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
  972. }
  973. if i >= end {
  974. write_string(b, "%!(NO VERB)");
  975. break;
  976. }
  977. verb, w := utf8.decode_rune(fmt[i..]);
  978. i += w;
  979. if verb == '%' {
  980. write_byte(b, '%');
  981. } else if !fi.good_arg_index {
  982. write_string(b, "%!(BAD ARGUMENT NUMBER)");
  983. } else if arg_index >= len(args) {
  984. write_string(b, "%!(MISSING ARGUMENT)");
  985. } else {
  986. fmt_arg(&fi, args[arg_index], verb);
  987. arg_index += 1;
  988. }
  989. }
  990. if !fi.reordered && arg_index < len(args) {
  991. write_string(b, "%!(EXTRA ");
  992. for arg, index in args[arg_index..] {
  993. if index > 0 do write_string(b, ", ");
  994. if arg == nil do write_string(b, "<nil>");
  995. else do fmt_arg(&fi, args[index], 'v');
  996. }
  997. write_string(b, ")");
  998. }
  999. return to_string(b^);
  1000. }