fmt.odin 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  1. package fmt
  2. import "core:runtime"
  3. import "core:os"
  4. import "core:mem"
  5. import "core:unicode/utf8"
  6. import "core:types"
  7. import "core:strconv"
  8. @(private)
  9. DEFAULT_BUFFER_SIZE :: 1<<12;
  10. String_Buffer :: distinct [dynamic]byte;
  11. Fmt_Info :: struct {
  12. minus: bool,
  13. plus: bool,
  14. space: bool,
  15. zero: bool,
  16. hash: bool,
  17. width_set: bool,
  18. prec_set: bool,
  19. width: int,
  20. prec: int,
  21. indent: int,
  22. reordered: bool,
  23. good_arg_index: bool,
  24. buf: ^String_Buffer,
  25. arg: any, // Temporary
  26. }
  27. string_buffer_from_slice :: proc(backing: []byte) -> String_Buffer {
  28. s := transmute(mem.Raw_Slice)backing;
  29. d := mem.Raw_Dynamic_Array{
  30. data = s.data,
  31. len = 0,
  32. cap = s.len,
  33. allocator = mem.nil_allocator(),
  34. };
  35. return transmute(String_Buffer)d;
  36. }
  37. to_string :: proc(buf: String_Buffer) -> string {
  38. return string(buf[:]);
  39. }
  40. write_string :: proc(buf: ^String_Buffer, s: string) {
  41. append_string(buf, s);
  42. }
  43. write_bytes :: proc(buf: ^String_Buffer, data: []byte) {
  44. append(buf, ..data);
  45. }
  46. write_byte :: proc(buf: ^String_Buffer, data: byte) {
  47. append(buf, data);
  48. }
  49. write_rune :: proc(buf: ^String_Buffer, r: rune) {
  50. if r < utf8.RUNE_SELF {
  51. write_byte(buf, byte(r));
  52. return;
  53. }
  54. b, n := utf8.encode_rune(r);
  55. write_bytes(buf, b[:n]);
  56. }
  57. write_encoded_rune :: proc(buf: ^String_Buffer, r: rune) {
  58. write_byte(buf, '\'');
  59. switch r {
  60. case '\a': write_string(buf, "\\a");
  61. case '\b': write_string(buf, "\\b");
  62. case '\e': write_string(buf, "\\e");
  63. case '\f': write_string(buf, "\\f");
  64. case '\n': write_string(buf, "\\n");
  65. case '\r': write_string(buf, "\\r");
  66. case '\t': write_string(buf, "\\t");
  67. case '\v': write_string(buf, "\\v");
  68. case:
  69. if r < 32 {
  70. write_string(buf, "\\x");
  71. b: [2]byte;
  72. s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil);
  73. switch len(s) {
  74. case 0: write_string(buf, "00");
  75. case 1: write_rune(buf, '0');
  76. case 2: write_string(buf, s);
  77. }
  78. } else {
  79. write_rune(buf, r);
  80. }
  81. }
  82. write_byte(buf, '\'');
  83. }
  84. write_u64 :: proc(buf: ^String_Buffer, i: u64, base: int) {
  85. b: [129]byte;
  86. s := strconv.append_bits(b[:], u64(i), base, false, 64, strconv.digits, nil);
  87. write_string(buf, s);
  88. }
  89. write_i64 :: proc(buf: ^String_Buffer, i: i64, base: int) {
  90. b: [129]byte;
  91. s := strconv.append_bits(b[:], u64(i), base, true, 64, strconv.digits, nil);
  92. write_string(buf, s);
  93. }
  94. fprint :: proc(fd: os.Handle, args: ..any) -> int {
  95. data: [DEFAULT_BUFFER_SIZE]byte;
  96. buf := string_buffer_from_slice(data[:]);
  97. res := sbprint(&buf, ..args);
  98. os.write_string(fd, res);
  99. return len(res);
  100. }
  101. fprintln :: proc(fd: os.Handle, args: ..any) -> int {
  102. data: [DEFAULT_BUFFER_SIZE]byte;
  103. buf := string_buffer_from_slice(data[:]);
  104. res := sbprintln(&buf, ..args);
  105. os.write_string(fd, res);
  106. return len(res);
  107. }
  108. fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
  109. data: [DEFAULT_BUFFER_SIZE]byte;
  110. buf := string_buffer_from_slice(data[:]);
  111. res := sbprintf(&buf, fmt, ..args);
  112. os.write_string(fd, res);
  113. return len(res);
  114. }
  115. // print* procedures return the number of bytes written
  116. print :: proc(args: ..any) -> int { return fprint(os.stdout, ..args); }
  117. print_err :: proc(args: ..any) -> int { return fprint(os.stderr, ..args); }
  118. println :: proc(args: ..any) -> int { return fprintln(os.stdout, ..args); }
  119. println_err :: proc(args: ..any) -> int { return fprintln(os.stderr, ..args); }
  120. printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args); }
  121. printf_err :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args); }
  122. // aprint* procedures return a string that was allocated with the current context
  123. // They must be freed accordingly
  124. aprint :: proc(args: ..any) -> string {
  125. buf := String_Buffer(make([dynamic]byte));
  126. sbprint(&buf, ..args);
  127. return to_string(buf);
  128. }
  129. aprintln :: proc(args: ..any) -> string {
  130. buf := String_Buffer(make([dynamic]byte));
  131. sbprintln(&buf, ..args);
  132. return to_string(buf);
  133. }
  134. aprintf :: proc(fmt: string, args: ..any) -> string {
  135. buf := String_Buffer(make([dynamic]byte));
  136. sbprintf(&buf, fmt, ..args);
  137. return to_string(buf);
  138. }
  139. // tprint* procedures return a string that was allocated with the current context's temporary allocator
  140. tprint :: proc(args: ..any) -> string {
  141. buf := String_Buffer(make([dynamic]byte, context.temp_allocator));
  142. sbprint(&buf, ..args);
  143. return to_string(buf);
  144. }
  145. tprintln :: proc(args: ..any) -> string {
  146. buf := String_Buffer(make([dynamic]byte, context.temp_allocator));
  147. sbprintln(&buf, ..args);
  148. return to_string(buf);
  149. }
  150. tprintf :: proc(fmt: string, args: ..any) -> string {
  151. buf := String_Buffer(make([dynamic]byte, context.temp_allocator));
  152. sbprintf(&buf, fmt, ..args);
  153. return to_string(buf);
  154. }
  155. // bprint* procedures return a string using a buffer from an array
  156. bprint :: proc(buf: []byte, args: ..any) -> string {
  157. sb := string_buffer_from_slice(buf[0:len(buf)]);
  158. return sbprint(&sb, ..args);
  159. }
  160. bprintln :: proc(buf: []byte, args: ..any) -> string {
  161. sb := string_buffer_from_slice(buf[0:len(buf)]);
  162. return sbprintln(&sb, ..args);
  163. }
  164. bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string {
  165. sb := string_buffer_from_slice(buf[0:len(buf)]);
  166. return sbprintf(&sb, fmt, ..args);
  167. }
  168. assertf :: proc "contextless" (condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool {
  169. if !condition {
  170. p := context.assertion_failure_proc;
  171. if p == nil {
  172. p = runtime.default_assertion_failure_proc;
  173. }
  174. message := tprintf(fmt, ..args);
  175. p("Runtime assertion", message, loc);
  176. }
  177. return condition;
  178. }
  179. panicf :: proc "contextless" (fmt: string, args: ..any, loc := #caller_location) {
  180. p := context.assertion_failure_proc;
  181. if p == nil {
  182. p = runtime.default_assertion_failure_proc;
  183. }
  184. message := tprintf(fmt, ..args);
  185. p("Panic", message, loc);
  186. }
  187. fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info) {
  188. data: [DEFAULT_BUFFER_SIZE]byte;
  189. buf := string_buffer_from_slice(data[:]);
  190. write_type(&buf, info);
  191. os.write(fd, buf[:]);
  192. }
  193. write_typeid :: proc(buf: ^String_Buffer, id: typeid) {
  194. write_type(buf, type_info_of(id));
  195. }
  196. write_type :: proc(buf: ^String_Buffer, ti: ^runtime.Type_Info) {
  197. if ti == nil {
  198. write_string(buf, "nil");
  199. return;
  200. }
  201. switch info in ti.variant {
  202. case runtime.Type_Info_Named:
  203. write_string(buf, info.name);
  204. case runtime.Type_Info_Integer:
  205. switch ti.id {
  206. case int: write_string(buf, "int");
  207. case uint: write_string(buf, "uint");
  208. case uintptr: write_string(buf, "uintptr");
  209. case:
  210. write_byte(buf, info.signed ? 'i' : 'u');
  211. write_i64(buf, i64(8*ti.size), 10);
  212. }
  213. case runtime.Type_Info_Rune:
  214. write_string(buf, "rune");
  215. case runtime.Type_Info_Float:
  216. write_byte(buf, 'f');
  217. write_i64(buf, i64(8*ti.size), 10);
  218. case runtime.Type_Info_Complex:
  219. write_string(buf, "complex");
  220. write_i64(buf, i64(8*ti.size), 10);
  221. case runtime.Type_Info_String:
  222. if info.is_cstring {
  223. write_string(buf, "cstring");
  224. } else {
  225. write_string(buf, "string");
  226. }
  227. case runtime.Type_Info_Boolean:
  228. switch ti.id {
  229. case bool: write_string(buf, "bool");
  230. case:
  231. write_byte(buf, 'b');
  232. write_i64(buf, i64(8*ti.size), 10);
  233. }
  234. case runtime.Type_Info_Any:
  235. write_string(buf, "any");
  236. case runtime.Type_Info_Type_Id:
  237. write_string(buf, "typeid");
  238. case runtime.Type_Info_Pointer:
  239. if info.elem == nil {
  240. write_string(buf, "rawptr");
  241. } else {
  242. write_string(buf, "^");
  243. write_type(buf, info.elem);
  244. }
  245. case runtime.Type_Info_Procedure:
  246. write_string(buf, "proc");
  247. if info.params == nil {
  248. write_string(buf, "()");
  249. } else {
  250. t := info.params.variant.(runtime.Type_Info_Tuple);
  251. write_string(buf, "(");
  252. for t, i in t.types {
  253. if i > 0 do write_string(buf, ", ");
  254. write_type(buf, t);
  255. }
  256. write_string(buf, ")");
  257. }
  258. if info.results != nil {
  259. write_string(buf, " -> ");
  260. write_type(buf, info.results);
  261. }
  262. case runtime.Type_Info_Tuple:
  263. count := len(info.names);
  264. if count != 1 do write_string(buf, "(");
  265. for name, i in info.names {
  266. if i > 0 do write_string(buf, ", ");
  267. t := info.types[i];
  268. if len(name) > 0 {
  269. write_string(buf, name);
  270. write_string(buf, ": ");
  271. }
  272. write_type(buf, t);
  273. }
  274. if count != 1 do write_string(buf, ")");
  275. case runtime.Type_Info_Array:
  276. write_string(buf, "[");
  277. write_i64(buf, i64(info.count), 10);
  278. write_string(buf, "]");
  279. write_type(buf, info.elem);
  280. case runtime.Type_Info_Dynamic_Array:
  281. write_string(buf, "[dynamic]");
  282. write_type(buf, info.elem);
  283. case runtime.Type_Info_Slice:
  284. write_string(buf, "[]");
  285. write_type(buf, info.elem);
  286. case runtime.Type_Info_Map:
  287. write_string(buf, "map[");
  288. write_type(buf, info.key);
  289. write_byte(buf, ']');
  290. write_type(buf, info.value);
  291. case runtime.Type_Info_Struct:
  292. write_string(buf, "struct ");
  293. if info.is_packed do write_string(buf, "#packed ");
  294. if info.is_raw_union do write_string(buf, "#raw_union ");
  295. if info.custom_align {
  296. write_string(buf, "#align ");
  297. write_i64(buf, i64(ti.align), 10);
  298. write_byte(buf, ' ');
  299. }
  300. write_byte(buf, '{');
  301. for name, i in info.names {
  302. if i > 0 do write_string(buf, ", ");
  303. write_string(buf, name);
  304. write_string(buf, ": ");
  305. write_type(buf, info.types[i]);
  306. }
  307. write_byte(buf, '}');
  308. case runtime.Type_Info_Union:
  309. write_string(buf, "union ");
  310. if info.custom_align {
  311. write_string(buf, "#align ");
  312. write_i64(buf, i64(ti.align), 10);
  313. write_byte(buf, ' ');
  314. }
  315. write_byte(buf, '{');
  316. for variant, i in info.variants {
  317. if i > 0 do write_string(buf, ", ");
  318. write_type(buf, variant);
  319. }
  320. write_string(buf, "}");
  321. case runtime.Type_Info_Enum:
  322. write_string(buf, "enum ");
  323. write_type(buf, info.base);
  324. write_string(buf, " {");
  325. for name, i in info.names {
  326. if i > 0 do write_string(buf, ", ");
  327. write_string(buf, name);
  328. }
  329. write_string(buf, "}");
  330. case runtime.Type_Info_Bit_Field:
  331. write_string(buf, "bit_field ");
  332. if ti.align != 1 {
  333. write_string(buf, "#align ");
  334. write_i64(buf, i64(ti.align), 10);
  335. write_rune(buf, ' ');
  336. }
  337. write_string(buf, " {");
  338. for name, i in info.names {
  339. if i > 0 do write_string(buf, ", ");
  340. write_string(buf, name);
  341. write_string(buf, ": ");
  342. write_i64(buf, i64(info.bits[i]), 10);
  343. }
  344. write_string(buf, "}");
  345. case runtime.Type_Info_Bit_Set:
  346. write_string(buf, "bit_set[");
  347. switch {
  348. case types.is_enum(info.elem):
  349. write_type(buf, info.elem);
  350. case types.is_rune(info.elem):
  351. write_encoded_rune(buf, rune(info.lower));
  352. write_string(buf, "..");
  353. write_encoded_rune(buf, rune(info.upper));
  354. case:
  355. write_i64(buf, info.lower, 10);
  356. write_string(buf, "..");
  357. write_i64(buf, info.upper, 10);
  358. }
  359. if info.underlying != nil {
  360. write_string(buf, "; ");
  361. write_type(buf, info.underlying);
  362. }
  363. write_byte(buf, ']');
  364. case runtime.Type_Info_Opaque:
  365. write_string(buf, "opaque ");
  366. write_type(buf, info.elem);
  367. }
  368. }
  369. _parse_int :: proc(s: string, offset: int) -> (result: int, new_offset: int, ok: bool) {
  370. is_digit :: inline proc(r: byte) -> bool { return '0' <= r && r <= '9' }
  371. new_offset = offset;
  372. for new_offset <= len(s) {
  373. c := s[new_offset];
  374. if !is_digit(c) do break;
  375. new_offset += 1;
  376. result *= 10;
  377. result += int(c)-'0';
  378. }
  379. ok = new_offset > offset;
  380. return;
  381. }
  382. _arg_number :: proc(fi: ^Fmt_Info, arg_index: int, format: string, offset, arg_count: int) -> (index, new_offset: int, ok: bool) {
  383. parse_arg_number :: proc(format: string) -> (int, int, bool) {
  384. if len(format) < 3 do return 0, 1, false;
  385. for i in 1..len(format)-1 {
  386. if format[i] == ']' {
  387. width, new_index, ok := _parse_int(format, 1);
  388. if !ok || new_index != i {
  389. return 0, i+1, false;
  390. }
  391. return width-1, i+1, true;
  392. }
  393. }
  394. return 0, 1, false;
  395. }
  396. if len(format) <= offset || format[offset] != '[' {
  397. return arg_index, offset, false;
  398. }
  399. fi.reordered = true;
  400. width: int;
  401. index, width, ok = parse_arg_number(format[offset:]);
  402. if ok && 0 <= index && index < arg_count {
  403. return index, offset+width, true;
  404. }
  405. fi.good_arg_index = false;
  406. return arg_index, offset+width, false;
  407. }
  408. int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
  409. num := 0;
  410. new_arg_index := arg_index;
  411. ok := true;
  412. if arg_index < len(args) {
  413. arg := args[arg_index];
  414. arg.id = runtime.typeid_base(arg.id);
  415. switch i in arg {
  416. case int: num = i;
  417. case i8: num = int(i);
  418. case i16: num = int(i);
  419. case i32: num = int(i);
  420. case i64: num = int(i);
  421. case u8: num = int(i);
  422. case u16: num = int(i);
  423. case u32: num = int(i);
  424. case u64: num = int(i);
  425. case:
  426. ok = false;
  427. }
  428. }
  429. return num, new_arg_index, ok;
  430. }
  431. fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) {
  432. write_string(buf, "%!");
  433. write_rune(buf, verb);
  434. write_byte(buf, '(');
  435. if arg.id != nil {
  436. write_typeid(buf, arg.id);
  437. write_byte(buf, '=');
  438. fmt_value(fi, arg, 'v');
  439. } else {
  440. write_string(buf, "<nil>");
  441. }
  442. write_byte(buf, ')');
  443. }
  444. fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) {
  445. switch verb {
  446. case 't', 'v':
  447. write_string(buf, b ? "true" : "false");
  448. case:
  449. fmt_bad_verb(fi, verb);
  450. }
  451. }
  452. fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) {
  453. if width <= 0 do return;
  454. pad_byte: byte = '0';
  455. if fi.space do pad_byte = ' ';
  456. for _ in 0..width-1 {
  457. write_byte(fi.buf, pad_byte);
  458. }
  459. }
  460. _fmt_int :: proc(fi: ^Fmt_Info, u: u64, base: int, is_signed: bool, bit_size: int, digits: string) {
  461. _, neg := strconv.is_integer_negative(u, is_signed, bit_size);
  462. BUF_SIZE :: 256;
  463. if fi.width_set || fi.prec_set {
  464. width := fi.width + fi.prec + 3; // 3 extra bytes for sign and prefix
  465. if width > BUF_SIZE {
  466. // TODO(bill):????
  467. panic("_fmt_int: buffer overrun. Width and precision too big");
  468. }
  469. }
  470. prec := 0;
  471. if fi.prec_set {
  472. prec = fi.prec;
  473. if prec == 0 && u == 0 {
  474. prev_zero := fi.zero;
  475. fi.zero = false;
  476. fmt_write_padding(fi, fi.width);
  477. fi.zero = prev_zero;
  478. return;
  479. }
  480. } else if fi.zero && fi.width_set {
  481. prec = fi.width;
  482. if neg || fi.plus || fi.space {
  483. // There needs to be space for the "sign"
  484. prec -= 1;
  485. }
  486. }
  487. switch base {
  488. case 2, 8, 10, 12, 16:
  489. break;
  490. case:
  491. panic("_fmt_int: unknown base, whoops");
  492. }
  493. buf: [256]byte;
  494. start := 0;
  495. using strconv.Int_Flag;
  496. flags: strconv.Int_Flags;
  497. if fi.hash && !fi.zero do flags |= {Prefix};
  498. if fi.plus do flags |= {Plus};
  499. if fi.space do flags |= {Space};
  500. s := strconv.append_bits(buf[start:], u, base, is_signed, bit_size, digits, flags);
  501. if fi.hash && fi.zero {
  502. c: byte = 0;
  503. switch base {
  504. case 2: c = 'b';
  505. case 8: c = 'o';
  506. case 12: c = 'z';
  507. case 16: c = 'x';
  508. }
  509. if c != 0 {
  510. write_byte(fi.buf, '0');
  511. write_byte(fi.buf, c);
  512. }
  513. }
  514. prev_zero := fi.zero;
  515. defer fi.zero = prev_zero;
  516. fi.zero = false;
  517. _pad(fi, s);
  518. }
  519. __DIGITS_LOWER := "0123456789abcdefx";
  520. __DIGITS_UPPER := "0123456789ABCDEFX";
  521. fmt_rune :: proc(fi: ^Fmt_Info, r: rune, verb: rune) {
  522. switch verb {
  523. case 'c', 'r', 'v':
  524. write_rune(fi.buf, r);
  525. case:
  526. fmt_int(fi, u64(r), false, 32, verb);
  527. }
  528. }
  529. fmt_int :: proc(fi: ^Fmt_Info, u: u64, is_signed: bool, bit_size: int, verb: rune) {
  530. switch verb {
  531. case 'v': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
  532. case 'b': _fmt_int(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER);
  533. case 'o': _fmt_int(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER);
  534. case 'd': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
  535. case 'z': _fmt_int(fi, u, 12, is_signed, bit_size, __DIGITS_LOWER);
  536. case 'x': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_LOWER);
  537. case 'X': _fmt_int(fi, u, 16, is_signed, bit_size, __DIGITS_UPPER);
  538. case 'c', 'r':
  539. fmt_rune(fi, rune(u), verb);
  540. case 'U':
  541. r := rune(u);
  542. if r < 0 || r > utf8.MAX_RUNE {
  543. fmt_bad_verb(fi, verb);
  544. } else {
  545. write_string(fi.buf, "U+");
  546. _fmt_int(fi, u, 16, false, bit_size, __DIGITS_UPPER);
  547. }
  548. case:
  549. fmt_bad_verb(fi, verb);
  550. }
  551. }
  552. _pad :: proc(fi: ^Fmt_Info, s: string) {
  553. if !fi.width_set {
  554. write_string(fi.buf, s);
  555. return;
  556. }
  557. width := fi.width - utf8.rune_count_from_string(s);
  558. if fi.minus { // right pad
  559. write_string(fi.buf, s);
  560. fmt_write_padding(fi, width);
  561. } else { // left pad
  562. fmt_write_padding(fi, width);
  563. write_string(fi.buf, s);
  564. }
  565. }
  566. fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) {
  567. switch verb {
  568. // case 'e', 'E', 'f', 'F', 'g', 'G', 'v':
  569. // case 'f', 'F', 'v':
  570. case 'f', 'F', 'v':
  571. prec: int = 3;
  572. if fi.prec_set do prec = fi.prec;
  573. buf: [386]byte;
  574. str := strconv.append_float(buf[1:], v, 'f', prec, bit_size);
  575. str = string(buf[:len(str)+1]);
  576. if str[1] == '+' || str[1] == '-' {
  577. str = str[1:];
  578. } else {
  579. str[0] = '+';
  580. }
  581. if fi.space && !fi.plus && str[0] == '+' {
  582. str[0] = ' ';
  583. }
  584. if len(str) > 1 && str[1] == 'N' && str[1] == 'I' {
  585. write_string(fi.buf, str);
  586. return;
  587. }
  588. if fi.plus || str[0] != '+' {
  589. if fi.zero && fi.width_set && fi.width > len(str) {
  590. write_byte(fi.buf, str[0]);
  591. fmt_write_padding(fi, fi.width - len(str));
  592. write_string(fi.buf, str[1:]);
  593. } else {
  594. _pad(fi, str);
  595. }
  596. } else {
  597. _pad(fi, str[1:]);
  598. }
  599. case:
  600. fmt_bad_verb(fi, verb);
  601. }
  602. }
  603. fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
  604. switch verb {
  605. case 's', 'v':
  606. write_string(fi.buf, s);
  607. case 'x', 'X':
  608. space := fi.space;
  609. fi.space = false;
  610. defer fi.space = space;
  611. for i in 0..len(s)-1 {
  612. if i > 0 && space do write_byte(fi.buf, ' ');
  613. char_set := __DIGITS_UPPER;
  614. if verb == 'x' do char_set = __DIGITS_LOWER;
  615. _fmt_int(fi, u64(s[i]), 16, false, 8, char_set);
  616. }
  617. case:
  618. fmt_bad_verb(fi, verb);
  619. }
  620. }
  621. fmt_cstring :: proc(fi: ^Fmt_Info, s: cstring, verb: rune) {
  622. fmt_string(fi, string(s), verb);
  623. }
  624. fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
  625. switch verb {
  626. case 'p', 'v':
  627. u := u64(uintptr(p));
  628. if !fi.hash || verb == 'v' {
  629. write_string(fi.buf, "0x");
  630. }
  631. _fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER);
  632. case:
  633. fmt_bad_verb(fi, verb);
  634. }
  635. }
  636. enum_value_to_string :: proc(v: any) -> (string, bool) {
  637. v.id = runtime.typeid_base(v.id);
  638. type_info := type_info_of(v.id);
  639. switch e in type_info.variant {
  640. case: return "", false;
  641. case runtime.Type_Info_Enum:
  642. get_str :: proc(i: $T, e: runtime.Type_Info_Enum) -> (string, bool) {
  643. if types.is_string(e.base) {
  644. for val, idx in e.values {
  645. if v, ok := val.(T); ok && v == i {
  646. return e.names[idx], true;
  647. }
  648. }
  649. } else if len(e.values) == 0 {
  650. return "", true;
  651. } else {
  652. for val, idx in e.values {
  653. if v, ok := val.(T); ok && v == i {
  654. return e.names[idx], true;
  655. }
  656. }
  657. }
  658. return "", false;
  659. }
  660. a := any{v.data, runtime.type_info_base(e.base).id};
  661. switch v in a {
  662. case rune: return get_str(v, e);
  663. case i8: return get_str(v, e);
  664. case i16: return get_str(v, e);
  665. case i32: return get_str(v, e);
  666. case i64: return get_str(v, e);
  667. case int: return get_str(v, e);
  668. case u8: return get_str(v, e);
  669. case u16: return get_str(v, e);
  670. case u32: return get_str(v, e);
  671. case u64: return get_str(v, e);
  672. case uint: return get_str(v, e);
  673. case uintptr: return get_str(v, e);
  674. }
  675. }
  676. return "", false;
  677. }
  678. string_to_enum_value :: proc($T: typeid, s: string) -> (T, bool) {
  679. ti := type_info_base(type_info_of(T));
  680. if e, ok := ti.variant.(Type_Info_Enum); ok {
  681. for str, idx in e.names {
  682. if s == str {
  683. // NOTE(bill): Unsafe cast
  684. ptr := cast(^T)&e.values[idx];
  685. return ptr^, true;
  686. }
  687. }
  688. }
  689. return T{}, false;
  690. }
  691. fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
  692. if v.id == nil || v.data == nil {
  693. write_string(fi.buf, "<nil>");
  694. return;
  695. }
  696. type_info := type_info_of(v.id);
  697. switch e in type_info.variant {
  698. case: fmt_bad_verb(fi, verb);
  699. case runtime.Type_Info_Enum:
  700. switch verb {
  701. case: fmt_bad_verb(fi, verb);
  702. case 'd', 'f':
  703. fmt_arg(fi, any{v.data, runtime.type_info_base(e.base).id}, verb);
  704. case 's', 'v':
  705. str, ok := enum_value_to_string(v);
  706. if !ok do str = "!%(BAD ENUM VALUE)";
  707. write_string(fi.buf, str);
  708. }
  709. }
  710. }
  711. enum_value_to_u64 :: proc(ev: runtime.Type_Info_Enum_Value) -> u64 {
  712. switch i in ev {
  713. case rune: return u64(i);
  714. case i8: return u64(i);
  715. case i16: return u64(i);
  716. case i32: return u64(i);
  717. case i64: return u64(i);
  718. case int: return u64(i);
  719. case u8: return u64(i);
  720. case u16: return u64(i);
  721. case u32: return u64(i);
  722. case u64: return u64(i);
  723. case uint: return u64(i);
  724. case uintptr: return u64(i);
  725. }
  726. return 0;
  727. }
  728. fmt_bit_set :: proc(fi: ^Fmt_Info, v: any, name: string = "") {
  729. type_info := type_info_of(v.id);
  730. switch info in type_info.variant {
  731. case runtime.Type_Info_Named:
  732. val := v;
  733. val.id = info.base.id;
  734. fmt_bit_set(fi, val, info.name);
  735. case runtime.Type_Info_Bit_Set:
  736. bits: u64;
  737. bit_size := u64(8*type_info.size);
  738. verb := 'b';
  739. switch bit_size {
  740. case 0: bits = 0;
  741. case 8: bits = u64( (^u8)(v.data)^);
  742. case 16: bits = u64((^u16)(v.data)^);
  743. case 32: bits = u64((^u32)(v.data)^);
  744. case 64: bits = u64((^u64)(v.data)^);
  745. case: panic("unknown bit_size size");
  746. }
  747. et := runtime.type_info_base(info.elem);
  748. if name != "" {
  749. write_string(fi.buf, name);
  750. } else {
  751. write_type(fi.buf, type_info);
  752. }
  753. write_byte(fi.buf, '{');
  754. defer write_byte(fi.buf, '}');
  755. e, is_enum := et.variant.(runtime.Type_Info_Enum);
  756. commas := 0;
  757. loop: for i in 0 .. bit_size-1 {
  758. if bits & (1<<i) == 0 {
  759. continue loop;
  760. }
  761. if commas > 0 do write_string(fi.buf, ", ");
  762. defer commas += 1;
  763. if is_enum do for ev, evi in e.values {
  764. v := enum_value_to_u64(ev);
  765. if v == i {
  766. write_string(fi.buf, e.names[evi]);
  767. continue loop;
  768. }
  769. }
  770. write_i64(fi.buf, i64(i), 10);
  771. }
  772. }
  773. }
  774. fmt_bit_field :: proc(fi: ^Fmt_Info, v: any, name: string = "") {
  775. type_info := type_info_of(v.id);
  776. switch info in type_info.variant {
  777. case runtime.Type_Info_Named:
  778. val := v;
  779. val.id = info.base.id;
  780. fmt_bit_field(fi, val, info.name);
  781. case runtime.Type_Info_Bit_Field:
  782. data: u64 = 0;
  783. switch type_info.size {
  784. case 1: data = cast(u64) (^u8)(v.data)^;
  785. case 2: data = cast(u64)(^u16)(v.data)^;
  786. case 4: data = cast(u64)(^u32)(v.data)^;
  787. case 8: data = cast(u64)(^u64)(v.data)^;
  788. }
  789. if name != "" {
  790. write_string(fi.buf, name);
  791. write_byte(fi.buf, '{');
  792. } else {
  793. write_string(fi.buf, "bit_field{");
  794. }
  795. for name, i in info.names {
  796. if i > 0 {
  797. write_string(fi.buf, ", ");
  798. }
  799. bits := u64(info.bits[i]);
  800. offset := u64(info.offsets[i]);
  801. write_string(fi.buf, name);
  802. write_string(fi.buf, " = ");
  803. n := 8*u64(size_of(u64));
  804. sa := n - bits;
  805. u := data>>offset;
  806. u <<= sa;
  807. u >>= sa;
  808. write_u64(fi.buf, u, 10);
  809. }
  810. write_byte(fi.buf, '}');
  811. case:
  812. write_string(fi.buf, "HERE");
  813. }
  814. }
  815. fmt_opaque :: proc(fi: ^Fmt_Info, v: any) {
  816. is_nil :: proc(data: rawptr, n: int) -> bool {
  817. if data == nil do return true;
  818. if n == 0 do return true;
  819. a := (^byte)(data);
  820. for i in 0..n-1 do if mem.ptr_offset(a, i)^ != 0 {
  821. return false;
  822. }
  823. return true;
  824. }
  825. rt :: runtime;
  826. type_info := type_info_of(v.id);
  827. if is_nil(v.data, type_info.size) {
  828. write_string(fi.buf, "nil");
  829. return;
  830. }
  831. if ot, ok := rt.type_info_base(type_info).variant.(rt.Type_Info_Opaque); ok {
  832. elem := rt.type_info_base(ot.elem);
  833. if elem == nil do return;
  834. write_type(fi.buf, type_info);
  835. write_byte(fi.buf, '{');
  836. defer write_byte(fi.buf, '}');
  837. switch in elem.variant {
  838. case rt.Type_Info_Integer, rt.Type_Info_Pointer, rt.Type_Info_Float:
  839. fmt_value(fi, any{v.data, elem.id}, 'v');
  840. case:
  841. // Okay
  842. }
  843. } else {
  844. write_type(fi.buf, type_info);
  845. write_byte(fi.buf, '{');
  846. defer write_byte(fi.buf, '}');
  847. }
  848. }
  849. fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
  850. if v.data == nil || v.id == nil {
  851. write_string(fi.buf, "<nil>");
  852. return;
  853. }
  854. type_info := type_info_of(v.id);
  855. switch info in type_info.variant {
  856. case runtime.Type_Info_Named:
  857. switch b in info.base.variant {
  858. case runtime.Type_Info_Struct:
  859. if verb != 'v' {
  860. fmt_bad_verb(fi, verb);
  861. return;
  862. }
  863. if b.is_raw_union {
  864. write_string(fi.buf, info.name);
  865. write_string(fi.buf, "{}");
  866. return;
  867. };
  868. write_string(fi.buf, info.name);
  869. write_byte(fi.buf, '{');
  870. hash := fi.hash; defer fi.hash = hash;
  871. indent := fi.indent; defer fi.indent -= 1;
  872. fi.hash = false;
  873. fi.indent += 1;
  874. if hash do write_byte(fi.buf, '\n');
  875. field_count := -1;
  876. for name, i in b.names {
  877. // if len(name) > 0 && name[0] == '_' do continue;
  878. field_count += 1;
  879. if !hash && field_count > 0 do write_string(fi.buf, ", ");
  880. if hash do for in 0..fi.indent-1 do write_byte(fi.buf, '\t');
  881. write_string(fi.buf, name);
  882. write_string(fi.buf, " = ");
  883. if t := b.types[i]; types.is_any(t) {
  884. write_string(fi.buf, "any{}");
  885. } else {
  886. data := rawptr(uintptr(v.data) + b.offsets[i]);
  887. fmt_arg(fi, any{data, t.id}, 'v');
  888. }
  889. if hash do write_string(fi.buf, ",\n");
  890. }
  891. if hash do for in 0..indent-1 do write_byte(fi.buf, '\t');
  892. write_byte(fi.buf, '}');
  893. case runtime.Type_Info_Bit_Set:
  894. fmt_bit_set(fi, v);
  895. case runtime.Type_Info_Bit_Field:
  896. fmt_bit_field(fi, v);
  897. case runtime.Type_Info_Opaque:
  898. fmt_opaque(fi, v);
  899. case:
  900. fmt_value(fi, any{v.data, info.base.id}, verb);
  901. }
  902. case runtime.Type_Info_Boolean: fmt_arg(fi, v, verb);
  903. case runtime.Type_Info_Integer: fmt_arg(fi, v, verb);
  904. case runtime.Type_Info_Rune: fmt_arg(fi, v, verb);
  905. case runtime.Type_Info_Float: fmt_arg(fi, v, verb);
  906. case runtime.Type_Info_Complex: fmt_arg(fi, v, verb);
  907. case runtime.Type_Info_String: fmt_arg(fi, v, verb);
  908. case runtime.Type_Info_Pointer:
  909. if v.id == typeid_of(^runtime.Type_Info) {
  910. write_type(fi.buf, (^^runtime.Type_Info)(v.data)^);
  911. } else {
  912. fmt_pointer(fi, (^rawptr)(v.data)^, verb);
  913. }
  914. case runtime.Type_Info_Array:
  915. write_byte(fi.buf, '[');
  916. defer write_byte(fi.buf, ']');
  917. for i in 0..info.count-1 {
  918. if i > 0 do write_string(fi.buf, ", ");
  919. data := uintptr(v.data) + uintptr(i*info.elem_size);
  920. fmt_arg(fi, any{rawptr(data), info.elem.id}, verb);
  921. }
  922. case runtime.Type_Info_Dynamic_Array:
  923. write_byte(fi.buf, '[');
  924. defer write_byte(fi.buf, ']');
  925. array := cast(^mem.Raw_Dynamic_Array)v.data;
  926. for i in 0..array.len-1 {
  927. if i > 0 do write_string(fi.buf, ", ");
  928. data := uintptr(array.data) + uintptr(i*info.elem_size);
  929. fmt_arg(fi, any{rawptr(data), info.elem.id}, verb);
  930. }
  931. case runtime.Type_Info_Slice:
  932. write_byte(fi.buf, '[');
  933. defer write_byte(fi.buf, ']');
  934. slice := cast(^mem.Raw_Slice)v.data;
  935. for i in 0..slice.len-1 {
  936. if i > 0 do write_string(fi.buf, ", ");
  937. data := uintptr(slice.data) + uintptr(i*info.elem_size);
  938. fmt_arg(fi, any{rawptr(data), info.elem.id}, verb);
  939. }
  940. case runtime.Type_Info_Map:
  941. if verb != 'v' {
  942. fmt_bad_verb(fi, verb);
  943. return;
  944. }
  945. write_string(fi.buf, "map[");
  946. defer write_byte(fi.buf, ']');
  947. m := (^mem.Raw_Map)(v.data);
  948. if m != nil {
  949. if info.generated_struct == nil {
  950. return;
  951. }
  952. entries := &m.entries;
  953. gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct);
  954. ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array);
  955. entry_type := ed.elem.variant.(runtime.Type_Info_Struct);
  956. entry_size := ed.elem_size;
  957. for i in 0..entries.len-1 {
  958. if i > 0 do write_string(fi.buf, ", ");
  959. data := uintptr(entries.data) + uintptr(i*entry_size);
  960. header := cast(^runtime.Map_Entry_Header)data;
  961. if types.is_string(info.key) {
  962. write_string(fi.buf, header.key.str);
  963. } else {
  964. fi := Fmt_Info{buf = fi.buf};
  965. fmt_arg(&fi, any{rawptr(&header.key.hash), info.key.id}, 'v');
  966. }
  967. write_string(fi.buf, "=");
  968. value := data + entry_type.offsets[2];
  969. fmt_arg(fi, any{rawptr(value), info.value.id}, 'v');
  970. }
  971. }
  972. case runtime.Type_Info_Struct:
  973. if info.is_raw_union {
  974. write_string(fi.buf, "(raw_union)");
  975. return;
  976. }
  977. write_byte(fi.buf, '{');
  978. defer write_byte(fi.buf, '}');
  979. fi.indent += 1; defer fi.indent -= 1;
  980. hash := fi.hash; defer fi.hash = hash;
  981. fi.hash = false;
  982. if hash do write_byte(fi.buf, '\n');
  983. for _, i in info.names {
  984. if !hash && i > 0 do write_string(fi.buf, ", ");
  985. if hash {
  986. for in 0..fi.indent-1 {
  987. write_byte(fi.buf, '\t');
  988. }
  989. }
  990. write_string(fi.buf, info.names[i]);
  991. write_string(fi.buf, " = ");
  992. if t := info.types[i]; types.is_any(t) {
  993. write_string(fi.buf, "any{}");
  994. } else {
  995. data := uintptr(v.data) + info.offsets[i];
  996. fmt_arg(fi, any{rawptr(data), t.id}, 'v');
  997. }
  998. if hash do write_string(fi.buf, ",\n");
  999. }
  1000. case runtime.Type_Info_Union:
  1001. tag_ptr := uintptr(v.data) + info.tag_offset;
  1002. tag_any := any{rawptr(tag_ptr), info.tag_type.id};
  1003. tag: i64 = -1;
  1004. switch i in tag_any {
  1005. case u8: tag = i64(i);
  1006. case i8: tag = i64(i);
  1007. case u16: tag = i64(i);
  1008. case i16: tag = i64(i);
  1009. case u32: tag = i64(i);
  1010. case i32: tag = i64(i);
  1011. case u64: tag = i64(i);
  1012. case i64: tag = i64(i);
  1013. case: panic("Invalid union tag type");
  1014. }
  1015. if v.data == nil || tag == 0 {
  1016. write_string(fi.buf, "nil");
  1017. } else {
  1018. id := info.variants[tag-1].id;
  1019. fmt_arg(fi, any{v.data, id}, verb);
  1020. }
  1021. case runtime.Type_Info_Enum:
  1022. fmt_enum(fi, v, verb);
  1023. case runtime.Type_Info_Procedure:
  1024. ptr := (^rawptr)(v.data)^;
  1025. if ptr == nil {
  1026. write_string(fi.buf, "nil");
  1027. } else {
  1028. write_typeid(fi.buf, v.id);
  1029. write_string(fi.buf, " @ ");
  1030. fmt_pointer(fi, ptr, 'p');
  1031. }
  1032. case runtime.Type_Info_Type_Id:
  1033. id := (^typeid)(v.data)^;
  1034. write_typeid(fi.buf, id);
  1035. case runtime.Type_Info_Bit_Field:
  1036. fmt_bit_field(fi, v);
  1037. case runtime.Type_Info_Bit_Set:
  1038. fmt_bit_set(fi, v);
  1039. case runtime.Type_Info_Opaque:
  1040. fmt_opaque(fi, v);
  1041. }
  1042. }
  1043. fmt_complex :: proc(fi: ^Fmt_Info, c: complex128, bits: int, verb: rune) {
  1044. switch verb {
  1045. case 'f', 'F', 'v':
  1046. r, i := real(c), imag(c);
  1047. fmt_float(fi, r, bits/2, verb);
  1048. if !fi.plus && i >= 0 {
  1049. write_rune(fi.buf, '+');
  1050. }
  1051. fmt_float(fi, i, bits/2, verb);
  1052. write_rune(fi.buf, 'i');
  1053. case:
  1054. fmt_bad_verb(fi, verb);
  1055. return;
  1056. }
  1057. }
  1058. fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
  1059. if arg == nil {
  1060. write_string(fi.buf, "<nil>");
  1061. return;
  1062. }
  1063. fi.arg = arg;
  1064. if verb == 'T' {
  1065. ti := type_info_of(arg.id);
  1066. switch a in arg {
  1067. case ^runtime.Type_Info: ti = a;
  1068. }
  1069. write_type(fi.buf, ti);
  1070. return;
  1071. }
  1072. base_arg := arg;
  1073. base_arg.id = runtime.typeid_base(base_arg.id);
  1074. switch a in base_arg {
  1075. case bool: fmt_bool(fi, bool(a), verb);
  1076. case b8: fmt_bool(fi, bool(a), verb);
  1077. case b16: fmt_bool(fi, bool(a), verb);
  1078. case b32: fmt_bool(fi, bool(a), verb);
  1079. case b64: fmt_bool(fi, bool(a), verb);
  1080. case any: fmt_arg(fi, a, verb);
  1081. case rune: fmt_rune(fi, a, verb);
  1082. case f32: fmt_float(fi, f64(a), 32, verb);
  1083. case f64: fmt_float(fi, a, 64, verb);
  1084. case complex64: fmt_complex(fi, complex128(a), 64, verb);
  1085. case complex128: fmt_complex(fi, a, 128, verb);
  1086. case i8: fmt_int(fi, u64(a), true, 8, verb);
  1087. case u8: fmt_int(fi, u64(a), false, 8, verb);
  1088. case i16: fmt_int(fi, u64(a), true, 16, verb);
  1089. case u16: fmt_int(fi, u64(a), false, 16, verb);
  1090. case i32: fmt_int(fi, u64(a), true, 32, verb);
  1091. case u32: fmt_int(fi, u64(a), false, 32, verb);
  1092. case i64: fmt_int(fi, u64(a), true, 64, verb);
  1093. case u64: fmt_int(fi, u64(a), false, 64, verb);
  1094. case int: fmt_int(fi, u64(a), true, 8*size_of(int), verb);
  1095. case uint: fmt_int(fi, u64(a), false, 8*size_of(uint), verb);
  1096. case uintptr: fmt_int(fi, u64(a), false, 8*size_of(uintptr), verb);
  1097. case string: fmt_string(fi, a, verb);
  1098. case cstring: fmt_cstring(fi, a, verb);
  1099. case typeid: write_typeid(fi.buf, a);
  1100. case: fmt_value(fi, arg, verb);
  1101. }
  1102. }
  1103. sbprint :: proc(buf: ^String_Buffer, args: ..any) -> string {
  1104. fi: Fmt_Info;
  1105. prev_string := false;
  1106. fi.buf = buf;
  1107. for arg, i in args {
  1108. is_string := arg != nil && types.is_string(type_info_of(arg.id));
  1109. if i > 0 && !is_string && !prev_string {
  1110. write_byte(buf, ' ');
  1111. }
  1112. fmt_value(&fi, args[i], 'v');
  1113. prev_string = is_string;
  1114. }
  1115. return to_string(buf^);
  1116. }
  1117. sbprintln :: proc(buf: ^String_Buffer, args: ..any) -> string {
  1118. fi: Fmt_Info;
  1119. fi.buf = buf;
  1120. for _, i in args {
  1121. if i > 0 do write_byte(buf, ' ');
  1122. fmt_value(&fi, args[i], 'v');
  1123. }
  1124. write_byte(buf, '\n');
  1125. return to_string(buf^);
  1126. }
  1127. sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> string {
  1128. fi: Fmt_Info;
  1129. arg_index: int = 0;
  1130. end := len(fmt);
  1131. was_prev_index := false;
  1132. loop: for i := 0; i < end; /**/ {
  1133. fi = Fmt_Info{buf = b, good_arg_index = true};
  1134. prev_i := i;
  1135. for i < end && fmt[i] != '%' {
  1136. i += 1;
  1137. }
  1138. if i > prev_i {
  1139. write_string(b, fmt[prev_i:i]);
  1140. }
  1141. if i >= end {
  1142. break loop;
  1143. }
  1144. // Process a "verb"
  1145. i += 1;
  1146. prefix_loop: for ; i < end; i += 1 {
  1147. switch fmt[i] {
  1148. case '+':
  1149. fi.plus = true;
  1150. case '-':
  1151. fi.minus = true;
  1152. fi.zero = false;
  1153. case ' ':
  1154. fi.space = true;
  1155. case '#':
  1156. fi.hash = true;
  1157. case '0':
  1158. fi.zero = !fi.minus;
  1159. case:
  1160. break prefix_loop;
  1161. }
  1162. }
  1163. arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
  1164. // Width
  1165. if i < end && fmt[i] == '*' {
  1166. i += 1;
  1167. fi.width, arg_index, fi.width_set = int_from_arg(args, arg_index);
  1168. if !fi.width_set {
  1169. write_string(b, "%!(BAD WIDTH)");
  1170. }
  1171. if fi.width < 0 {
  1172. fi.width = -fi.width;
  1173. fi.minus = true;
  1174. fi.zero = false;
  1175. }
  1176. was_prev_index = false;
  1177. } else {
  1178. fi.width, i, fi.width_set = _parse_int(fmt, i);
  1179. if was_prev_index && fi.width_set { // %[6]2d
  1180. fi.good_arg_index = false;
  1181. }
  1182. }
  1183. // Precision
  1184. if i < end && fmt[i] == '.' {
  1185. i += 1;
  1186. if was_prev_index { // %[6].2d
  1187. fi.good_arg_index = false;
  1188. }
  1189. if i < end && fmt[i] == '*' {
  1190. arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
  1191. i += 1;
  1192. fi.prec, arg_index, fi.prec_set = int_from_arg(args, arg_index);
  1193. if fi.prec < 0 {
  1194. fi.prec = 0;
  1195. fi.prec_set = false;
  1196. }
  1197. if !fi.prec_set {
  1198. write_string(fi.buf, "%!(BAD PRECISION)");
  1199. }
  1200. was_prev_index = false;
  1201. } else {
  1202. fi.prec, i, fi.prec_set = _parse_int(fmt, i);
  1203. if !fi.prec_set {
  1204. // fi.prec_set = true;
  1205. // fi.prec = 0;
  1206. }
  1207. }
  1208. }
  1209. if !was_prev_index {
  1210. arg_index, i, was_prev_index = _arg_number(&fi, arg_index, fmt, i, len(args));
  1211. }
  1212. if i >= end {
  1213. write_string(b, "%!(NO VERB)");
  1214. break loop;
  1215. }
  1216. verb, w := utf8.decode_rune_from_string(fmt[i:]);
  1217. i += w;
  1218. switch {
  1219. case verb == '%':
  1220. write_byte(b, '%');
  1221. case !fi.good_arg_index:
  1222. write_string(b, "%!(BAD ARGUMENT NUMBER)");
  1223. case arg_index >= len(args):
  1224. write_string(b, "%!(MISSING ARGUMENT)");
  1225. case:
  1226. fmt_arg(&fi, args[arg_index], verb);
  1227. arg_index += 1;
  1228. }
  1229. }
  1230. if !fi.reordered && arg_index < len(args) {
  1231. write_string(b, "%!(EXTRA ");
  1232. for arg, index in args[arg_index:] {
  1233. if index > 0 do write_string(b, ", ");
  1234. if arg == nil do write_string(b, "<nil>");
  1235. else do fmt_arg(&fi, args[index], 'v');
  1236. }
  1237. write_string(b, ")");
  1238. }
  1239. return to_string(b^);
  1240. }