fmt.odin 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. #import "os.odin";
  2. #import "mem.odin";
  3. #import "utf8.odin";
  4. PRINT_BUF_SIZE :: 1<<12;
  5. Buffer :: struct {
  6. data: []byte;
  7. length: int;
  8. }
  9. fprint :: proc(fd: os.Handle, args: ...any) -> int {
  10. data: [PRINT_BUF_SIZE]byte;
  11. buf := Buffer{data[:], 0};
  12. bprint(^buf, ...args);
  13. os.write(fd, buf.data[:buf.length]);
  14. return buf.length;
  15. }
  16. fprintln :: proc(fd: os.Handle, args: ...any) -> int {
  17. data: [PRINT_BUF_SIZE]byte;
  18. buf := Buffer{data[:], 0};
  19. bprintln(^buf, ...args);
  20. os.write(fd, buf.data[:buf.length]);
  21. return buf.length;
  22. }
  23. fprintf :: proc(fd: os.Handle, fmt: string, args: ...any) -> int {
  24. data: [PRINT_BUF_SIZE]byte;
  25. buf := Buffer{data[:], 0};
  26. bprintf(^buf, fmt, ...args);
  27. os.write(fd, buf.data[:buf.length]);
  28. return buf.length;
  29. }
  30. print :: proc(args: ...any) -> int {
  31. return fprint(os.stdout, ...args);
  32. }
  33. println :: proc(args: ...any) -> int {
  34. return fprintln(os.stdout, ...args);
  35. }
  36. printf :: proc(fmt: string, args: ...any) -> int {
  37. return fprintf(os.stdout, fmt, ...args);
  38. }
  39. fprint_type :: proc(fd: os.Handle, info: ^Type_Info) {
  40. data: [PRINT_BUF_SIZE]byte;
  41. buf := Buffer{data[:], 0};
  42. bprint_type(^buf, info);
  43. os.write(fd, buf.data[:buf.length]);
  44. }
  45. print_byte_buffer :: proc(buf: ^Buffer, b: []byte) {
  46. if buf.length < buf.data.count {
  47. n := min(buf.data.count-buf.length, b.count);
  48. if n > 0 {
  49. copy(buf.data[buf.length:], b[:n]);
  50. buf.length += n;
  51. }
  52. }
  53. }
  54. bprint_string :: proc(buf: ^Buffer, s: string) {
  55. print_byte_buffer(buf, s as []byte);
  56. }
  57. byte_reverse :: proc(b: []byte) {
  58. n := b.count;
  59. for i : 0..<n/2 {
  60. b[i], b[n-1-i] = b[n-1-i], b[i];
  61. }
  62. }
  63. bprint_rune :: proc(buf: ^Buffer, r: rune) {
  64. b, n := utf8.encode_rune(r);
  65. bprint_string(buf, b[:n] as string);
  66. }
  67. bprint_space :: proc(buf: ^Buffer) { bprint_rune(buf, ' '); }
  68. bprint_nl :: proc (buf: ^Buffer) { bprint_rune(buf, '\n'); }
  69. __NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
  70. bprint_bool :: proc(buffer: ^Buffer, b: bool) {
  71. bprint_string(buffer, if b { give "true" } else { give "false" });
  72. }
  73. bprint_pointer :: proc(buffer: ^Buffer, p: rawptr) #inline {
  74. bprint_string(buffer, "0x");
  75. bprint_u64(buffer, p as uint as u64);
  76. }
  77. // bprint_f16 :: proc(buffer: ^Buffer, f: f32) #inline { print__f64(buffer, f as f64, 4); }
  78. bprint_f32 :: proc(buffer: ^Buffer, f: f32) #inline { print__f64(buffer, f as f64, 7); }
  79. bprint_f64 :: proc(buffer: ^Buffer, f: f64) #inline { print__f64(buffer, f as f64, 16); }
  80. bprint_u64 :: proc(buffer: ^Buffer, value: u64) {
  81. i := value;
  82. buf :[20]byte;
  83. len := 0;
  84. if i == 0 {
  85. buf[len] = '0';
  86. len += 1;
  87. }
  88. while i > 0 {
  89. buf[len] = __NUM_TO_CHAR_TABLE[i % 10];
  90. len += 1;
  91. i /= 10;
  92. }
  93. byte_reverse(buf[:len]);
  94. bprint_string(buffer, buf[:len] as string);
  95. }
  96. bprint_i64 :: proc(buffer: ^Buffer, value: i64) {
  97. // TODO(bill): Cleanup printing
  98. i := value;
  99. if i < 0 {
  100. i = -i;
  101. bprint_rune(buffer, '-');
  102. }
  103. bprint_u64(buffer, i as u64);
  104. }
  105. /*
  106. bprint_u128 :: proc(buffer: ^Buffer, value u128) {
  107. a := value transmute [2]u64;
  108. if a[1] != 0 {
  109. bprint_u64(buffer, a[1]);
  110. }
  111. bprint_u64(buffer, a[0]);
  112. }
  113. bprint_i128 :: proc(buffer: ^Buffer, value i128) {
  114. i := value;
  115. if i < 0 {
  116. i = -i;
  117. bprint_rune(buffer, '-');
  118. }
  119. bprint_u128(buffer, i as u128);
  120. }
  121. */
  122. print__f64 :: proc(buffer: ^Buffer, value: f64, decimal_places: int) {
  123. f := value;
  124. if f == 0 {
  125. bprint_rune(buffer, '0');
  126. return;
  127. }
  128. if f < 0 {
  129. bprint_rune(buffer, '-');
  130. f = -f;
  131. }
  132. i := f as u64;
  133. bprint_u64(buffer, i);
  134. f -= i as f64;
  135. bprint_rune(buffer, '.');
  136. mult: f64 = 10.0;
  137. while decimal_places >= 0 {
  138. i = (f * mult) as u64;
  139. bprint_u64(buffer, i as u64);
  140. f -= i as f64 / mult;
  141. mult *= 10;
  142. decimal_places -= 1;
  143. }
  144. }
  145. bprint_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
  146. if ti == nil {
  147. return;
  148. }
  149. using Type_Info;
  150. match type info : ti {
  151. case Named:
  152. bprint_string(buf, info.name);
  153. case Integer:
  154. match {
  155. case ti == type_info(int): bprint_string(buf, "int");
  156. case ti == type_info(uint): bprint_string(buf, "uint");
  157. default:
  158. bprint_string(buf, if info.signed { give "i" } else { give "u"});
  159. bprint_u64(buf, 8*info.size as u64);
  160. }
  161. case Float:
  162. match info.size {
  163. case 4: bprint_string(buf, "f32");
  164. case 8: bprint_string(buf, "f64");
  165. }
  166. case String: bprint_string(buf, "string");
  167. case Boolean: bprint_string(buf, "bool");
  168. case Pointer:
  169. if info.elem == nil {
  170. bprint_string(buf, "rawptr");
  171. } else {
  172. bprint_string(buf, "^");
  173. bprint_type(buf, info.elem);
  174. }
  175. case Maybe:
  176. bprint_string(buf, "?");
  177. bprint_type(buf, info.elem);
  178. case Procedure:
  179. bprint_string(buf, "proc");
  180. if info.params == nil {
  181. bprint_string(buf, "()");
  182. } else {
  183. count := (info.params as ^Tuple).fields.count;
  184. if count == 1 { bprint_string(buf, "("); }
  185. bprint_type(buf, info.params);
  186. if count == 1 { bprint_string(buf, ")"); }
  187. }
  188. if info.results != nil {
  189. bprint_string(buf, " -> ");
  190. bprint_type(buf, info.results);
  191. }
  192. case Tuple:
  193. count := info.fields.count;
  194. if count != 1 { bprint_string(buf, "("); }
  195. for i : 0..<count {
  196. if i > 0 { bprint_string(buf, ", "); }
  197. f := info.fields[i];
  198. if f.name.count > 0 {
  199. bprint_string(buf, f.name);
  200. bprint_string(buf, ": ");
  201. }
  202. bprint_type(buf, f.type_info);
  203. }
  204. if count != 1 { bprint_string(buf, ")"); }
  205. case Array:
  206. bprint_string(buf, "[");
  207. bprint_i64(buf, info.count as i64);
  208. bprint_string(buf, "]");
  209. bprint_type(buf, info.elem);
  210. case Slice:
  211. bprint_string(buf, "[");
  212. bprint_string(buf, "]");
  213. bprint_type(buf, info.elem);
  214. case Vector:
  215. bprint_string(buf, "[vector ");
  216. bprint_i64(buf, info.count as i64);
  217. bprint_string(buf, "]");
  218. bprint_type(buf, info.elem);
  219. case Struct:
  220. bprint_string(buf, "struct ");
  221. if info.packed { bprint_string(buf, "#packed "); }
  222. if info.ordered { bprint_string(buf, "#ordered "); }
  223. bprint_string(buf, "{");
  224. for field, i : info.fields {
  225. if i > 0 {
  226. bprint_string(buf, ", ");
  227. }
  228. bprint_any(buf, field.name);
  229. bprint_string(buf, ": ");
  230. bprint_type(buf, field.type_info);
  231. }
  232. bprint_string(buf, "}");
  233. case Union:
  234. bprint_string(buf, "union {");
  235. for field, i : info.fields {
  236. if i > 0 {
  237. bprint_string(buf, ", ");
  238. }
  239. bprint_any(buf, field.name);
  240. bprint_string(buf, ": ");
  241. bprint_type(buf, field.type_info);
  242. }
  243. bprint_string(buf, "}");
  244. case Raw_Union:
  245. bprint_string(buf, "raw_union {");
  246. for field, i : info.fields {
  247. if i > 0 {
  248. bprint_string(buf, ", ");
  249. }
  250. bprint_any(buf, field.name);
  251. bprint_string(buf, ": ");
  252. bprint_type(buf, field.type_info);
  253. }
  254. bprint_string(buf, "}");
  255. case Enum:
  256. bprint_string(buf, "enum ");
  257. bprint_type(buf, info.base);
  258. bprint_string(buf, " {}");
  259. }
  260. }
  261. make_any :: proc(type_info: ^Type_Info, data: rawptr) -> any {
  262. a :any;
  263. a.type_info = type_info;
  264. a.data = data;
  265. return a;
  266. }
  267. bprint_any :: proc(buf: ^Buffer, arg: any) {
  268. if arg.type_info == nil {
  269. bprint_string(buf, "<nil>");
  270. return;
  271. }
  272. if arg.data == nil {
  273. bprint_string(buf, "<nil>");
  274. return;
  275. }
  276. using Type_Info;
  277. match type info : arg.type_info {
  278. case Named:
  279. a := make_any(info.base, arg.data);
  280. match type b : info.base {
  281. case Struct:
  282. bprint_string(buf, info.name);
  283. bprint_string(buf, "{");
  284. for f, i : b.fields {
  285. if i > 0 {
  286. bprint_string(buf, ", ");
  287. }
  288. bprint_string(buf, f.name);
  289. // bprint_any(buf, f.offset);
  290. bprint_string(buf, " = ");
  291. data := arg.data as ^byte + f.offset;
  292. bprint_any(buf, make_any(f.type_info, data));
  293. }
  294. bprint_string(buf, "}");
  295. default:
  296. bprint_any(buf, a);
  297. }
  298. case Integer:
  299. match type i : arg {
  300. case i8: bprint_i64(buf, i as i64);
  301. case u8: bprint_u64(buf, i as u64);
  302. case i16: bprint_i64(buf, i as i64);
  303. case u16: bprint_u64(buf, i as u64);
  304. case i32: bprint_i64(buf, i as i64);
  305. case u32: bprint_u64(buf, i as u64);
  306. case i64: bprint_i64(buf, i);
  307. case u64: bprint_u64(buf, i);
  308. // case i128: bprint_i128(buf, i);
  309. // case u128: bprint_u128(buf, i);
  310. case int: bprint_i64(buf, i as i64);
  311. case uint: bprint_u64(buf, i as u64);
  312. }
  313. case Float:
  314. match type f : arg {
  315. // case f16: bprint_f64(buf, f as f64);
  316. case f32: bprint_f32(buf, f);
  317. case f64: bprint_f64(buf, f);
  318. // case f128: bprint_f64(buf, f as f64);
  319. }
  320. case String:
  321. match type s : arg {
  322. case string: bprint_string(buf, s);
  323. }
  324. case Boolean:
  325. match type b : arg {
  326. case bool: bprint_bool(buf, b);
  327. }
  328. case Pointer:
  329. match type p : arg {
  330. case ^Type_Info: bprint_type(buf, p);
  331. default: bprint_pointer(buf, (arg.data as ^rawptr)^);
  332. }
  333. case Maybe:
  334. size := mem.size_of_type_info(info.elem);
  335. data := slice_ptr(arg.data as ^byte, size+1);
  336. if data[size] != 0 {
  337. bprint_any(buf, make_any(info.elem, arg.data));
  338. } else {
  339. bprint_string(buf, "nil");
  340. }
  341. case Array:
  342. bprintf(buf, "[%]%{", info.count, info.elem);
  343. defer bprint_string(buf, "}");
  344. for i : 0..<info.count {
  345. if i > 0 {
  346. bprint_string(buf, ", ");
  347. }
  348. data := arg.data as ^byte + i*info.elem_size;
  349. bprint_any(buf, make_any(info.elem, data));
  350. }
  351. case Slice:
  352. slice := arg.data as ^[]byte;
  353. bprintf(buf, "[]%{", info.elem);
  354. defer bprint_string(buf, "}");
  355. for i : 0..<slice.count {
  356. if i > 0 {
  357. bprint_string(buf, ", ");
  358. }
  359. data := slice.data + i*info.elem_size;
  360. bprint_any(buf, make_any(info.elem, data));
  361. }
  362. case Vector:
  363. is_bool :: proc(type_info: ^Type_Info) -> bool {
  364. match type info : type_info {
  365. case Named:
  366. return is_bool(info.base);
  367. case Boolean:
  368. return true;
  369. }
  370. return false;
  371. }
  372. bprintf(buf, "[vector %]%{", info.count, info.elem);
  373. defer bprint_string(buf, "}");
  374. if is_bool(info.elem) {
  375. return;
  376. }
  377. for i : 0..<info.count {
  378. if i > 0 {
  379. bprint_string(buf, ", ");
  380. }
  381. data := arg.data as ^byte + i*info.elem_size;
  382. bprint_any(buf, make_any(info.elem, data));
  383. }
  384. case Struct:
  385. bprintf(buf, "%{", arg.type_info);
  386. defer bprint_string(buf, "}");
  387. for f, i : info.fields {
  388. if i > 0 {
  389. bprint_string(buf, ", ");
  390. }
  391. bprint_string(buf, f.name);
  392. bprint_string(buf, " = ");
  393. data := arg.data as ^byte + f.offset;
  394. ti := f.type_info;
  395. bprint_any(buf, make_any(ti, data));
  396. }
  397. case Union:
  398. bprint_string(buf, "(union)");
  399. case Raw_Union:
  400. bprint_string(buf, "(raw_union)");
  401. case Enum:
  402. bprint_any(buf, make_any(info.base, arg.data));
  403. case Procedure:
  404. bprint_type(buf, arg.type_info);
  405. bprint_string(buf, " @ ");
  406. bprint_pointer(buf, (arg.data as ^rawptr)^);
  407. }
  408. }
  409. bprintf :: proc(buf: ^Buffer, fmt: string, args: ...any) -> int {
  410. is_digit :: proc(r: rune) -> bool #inline {
  411. return '0' <= r && r <= '9';
  412. }
  413. parse_int :: proc(s: string, offset: int) -> (int, int) {
  414. result := 0;
  415. for _ : offset..<s.count {
  416. c := s[offset] as rune;
  417. if !is_digit(c) {
  418. break;
  419. }
  420. result *= 10;
  421. result += (c - '0') as int;
  422. }
  423. return result, offset;
  424. }
  425. prev := 0;
  426. implicit_index := 0;
  427. while i := 0; i < fmt.count { defer i += 1;
  428. r := fmt[i] as rune;
  429. index := implicit_index;
  430. if r != '%' {
  431. continue;
  432. }
  433. bprint_string(buf, fmt[prev:i]);
  434. i += 1; // Skip %
  435. if i < fmt.count {
  436. next := fmt[i] as rune;
  437. if next == '%' {
  438. bprint_string(buf, "%");
  439. i += 1;
  440. prev = i;
  441. continue;
  442. }
  443. if is_digit(next) {
  444. index, i = parse_int(fmt, i);
  445. }
  446. }
  447. if 0 <= index && index < args.count {
  448. bprint_any(buf, args[index]);
  449. implicit_index = index+1;
  450. } else {
  451. // TODO(bill): Error check index out bounds
  452. bprint_string(buf, "<invalid>");
  453. }
  454. prev = i;
  455. }
  456. bprint_string(buf, fmt[prev:]);
  457. return buf.length;
  458. }
  459. bprint :: proc(buf: ^Buffer, args: ...any) -> int {
  460. is_type_string :: proc(info: ^Type_Info) -> bool {
  461. using Type_Info;
  462. if info == nil {
  463. return false;
  464. }
  465. match type i : type_info_base(info) {
  466. case String:
  467. return true;
  468. }
  469. return false;
  470. }
  471. prev_string := false;
  472. for arg, i : args {
  473. is_string := arg.data != nil && is_type_string(arg.type_info);
  474. if i > 0 && !is_string && !prev_string {
  475. bprint_space(buf);
  476. }
  477. bprint_any(buf, arg);
  478. prev_string = is_string;
  479. }
  480. return buf.length;
  481. }
  482. bprintln :: proc(buf: ^Buffer, args: ...any) -> int {
  483. for arg, i : args {
  484. if i > 0 {
  485. bprint_space(buf);
  486. }
  487. bprint_any(buf, arg);
  488. }
  489. bprint_nl(buf);
  490. return buf.length;
  491. }