fmt.odin 23 KB

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