file_util.odin 3.0 KB

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