file_util.odin 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package os2
  2. import "core:mem"
  3. import "core:strconv"
  4. import "core:unicode/utf8"
  5. write_string :: proc(fd: Handle, s: string) -> (n: int, err: Error) {
  6. return write(fd, transmute([]byte)s);
  7. }
  8. write_byte :: proc(fd: Handle, b: byte) -> (n: int, err: Error) {
  9. return write(fd, []byte{b});
  10. }
  11. write_rune :: proc(fd: Handle, r: rune) -> (n: int, err: Error) {
  12. if r < utf8.RUNE_SELF {
  13. return write_byte(fd, byte(r));
  14. }
  15. b: [4]byte;
  16. b, n = utf8.encode_rune(r);
  17. return write(fd, b[:n]);
  18. }
  19. write_encoded_rune :: proc(fd: Handle, r: rune) -> (n: int, err: Error) {
  20. wrap :: proc(m: int, merr: Error, n: ^int, err: ^Error) -> bool {
  21. n^ += m;
  22. if merr != nil {
  23. err^ = merr;
  24. return true;
  25. }
  26. return false;
  27. }
  28. if wrap(write_byte(fd, '\''), &n, &err) { return; }
  29. switch r {
  30. case '\a': if wrap(write_string(fd, "\\a"), &n, &err) { return; }
  31. case '\b': if wrap(write_string(fd, "\\b"), &n, &err) { return; }
  32. case '\e': if wrap(write_string(fd, "\\e"), &n, &err) { return; }
  33. case '\f': if wrap(write_string(fd, "\\f"), &n, &err) { return; }
  34. case '\n': if wrap(write_string(fd, "\\n"), &n, &err) { return; }
  35. case '\r': if wrap(write_string(fd, "\\r"), &n, &err) { return; }
  36. case '\t': if wrap(write_string(fd, "\\t"), &n, &err) { return; }
  37. case '\v': if wrap(write_string(fd, "\\v"), &n, &err) { return; }
  38. case:
  39. if r < 32 {
  40. if wrap(write_string(fd, "\\x"), &n, &err) { return; }
  41. b: [2]byte;
  42. s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil);
  43. switch len(s) {
  44. case 0: if wrap(write_string(fd, "00"), &n, &err) { return; }
  45. case 1: if wrap(write_rune(fd, '0'), &n, &err) { return; }
  46. case 2: if wrap(write_string(fd, s), &n, &err) { return; }
  47. }
  48. } else {
  49. if wrap(write_rune(fd, r), &n, &err) { return; }
  50. }
  51. }
  52. _ = wrap(write_byte(fd, '\''), &n, &err);
  53. return;
  54. }
  55. write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (n: int, err: Error) {
  56. s := transmute([]byte)mem.Raw_Slice{data, len};
  57. return write(fd, s);
  58. }
  59. read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (n: int, err: Error) {
  60. s := transmute([]byte)mem.Raw_Slice{data, len};
  61. return read(fd, s);
  62. }
  63. read_entire_file :: proc(name: string, allocator := context.allocator) -> ([]byte, Error) {
  64. f, ferr := open(name);
  65. if ferr != nil {
  66. return nil, ferr;
  67. }
  68. defer close(f);
  69. size: int;
  70. if size64, err := file_size(f); err == nil {
  71. if i64(int(size64)) != size64 {
  72. size = int(size64);
  73. }
  74. }
  75. size += 1; // for EOF
  76. // TODO(bill): Is this correct logic?
  77. total: int;
  78. data := make([]byte, size, allocator);
  79. for {
  80. n, err := read(f, data[total:]);
  81. total += n;
  82. if err != nil {
  83. if err == .EOF {
  84. err = nil;
  85. }
  86. return data[:total], err;
  87. }
  88. }
  89. }
  90. write_entire_file :: proc(name: string, data: []byte, perm: File_Mode, truncate := true) -> Error {
  91. flags := O_WRONLY|O_CREATE;
  92. if truncate {
  93. flags |= O_TRUNC;
  94. }
  95. f, err := open_file(name, flags, perm);
  96. if err != nil {
  97. return err;
  98. }
  99. _, err = write(f, data);
  100. if cerr := close(f); cerr != nil && err == nil {
  101. err = cerr;
  102. }
  103. return err;
  104. }