os.odin 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package os
  2. import "core:mem"
  3. import "core:strconv"
  4. import "core:unicode/utf8"
  5. OS :: ODIN_OS
  6. ARCH :: ODIN_ARCH
  7. ENDIAN :: ODIN_ENDIAN
  8. write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
  9. return write(fd, transmute([]byte)str)
  10. }
  11. write_byte :: proc(fd: Handle, b: byte) -> (int, Errno) {
  12. return write(fd, []byte{b})
  13. }
  14. write_rune :: proc(fd: Handle, r: rune) -> (int, Errno) {
  15. if r < utf8.RUNE_SELF {
  16. return write_byte(fd, byte(r))
  17. }
  18. b, n := utf8.encode_rune(r)
  19. return write(fd, b[:n])
  20. }
  21. write_encoded_rune :: proc(fd: Handle, r: rune) {
  22. write_byte(fd, '\'')
  23. switch r {
  24. case '\a': write_string(fd, "\\a")
  25. case '\b': write_string(fd, "\\b")
  26. case '\e': write_string(fd, "\\e")
  27. case '\f': write_string(fd, "\\f")
  28. case '\n': write_string(fd, "\\n")
  29. case '\r': write_string(fd, "\\r")
  30. case '\t': write_string(fd, "\\t")
  31. case '\v': write_string(fd, "\\v")
  32. case:
  33. if r < 32 {
  34. write_string(fd, "\\x")
  35. b: [2]byte
  36. s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil)
  37. switch len(s) {
  38. case 0: write_string(fd, "00")
  39. case 1: write_rune(fd, '0')
  40. case 2: write_string(fd, s)
  41. }
  42. } else {
  43. write_rune(fd, r)
  44. }
  45. }
  46. write_byte(fd, '\'')
  47. }
  48. file_size_from_path :: proc(path: string) -> i64 {
  49. fd, err := open(path, O_RDONLY, 0)
  50. if err != 0 {
  51. return -1
  52. }
  53. defer close(fd)
  54. length: i64
  55. if length, err = file_size(fd); err != 0 {
  56. return -1
  57. }
  58. return length
  59. }
  60. read_entire_file :: proc(name: string, allocator := context.allocator) -> (data: []byte, success: bool) {
  61. context.allocator = allocator
  62. fd, err := open(name, O_RDONLY, 0)
  63. if err != 0 {
  64. return nil, false
  65. }
  66. defer close(fd)
  67. length: i64
  68. if length, err = file_size(fd); err != 0 {
  69. return nil, false
  70. }
  71. if length <= 0 {
  72. return nil, true
  73. }
  74. data = make([]byte, int(length))
  75. if data == nil {
  76. return nil, false
  77. }
  78. bytes_read, read_err := read(fd, data)
  79. if read_err != ERROR_NONE {
  80. delete(data)
  81. return nil, false
  82. }
  83. return data[:bytes_read], true
  84. }
  85. write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (success: bool) {
  86. flags: int = O_WRONLY|O_CREATE
  87. if truncate {
  88. flags |= O_TRUNC
  89. }
  90. mode: int = 0
  91. when OS == "linux" || OS == "darwin" {
  92. // NOTE(justasd): 644 (owner read, write; group read; others read)
  93. mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
  94. }
  95. fd, err := open(name, flags, mode)
  96. if err != 0 {
  97. return false
  98. }
  99. defer close(fd)
  100. _, write_err := write(fd, data)
  101. return write_err == 0
  102. }
  103. write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
  104. s := transmute([]byte)mem.Raw_Slice{data, len}
  105. return write(fd, s)
  106. }
  107. read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
  108. s := transmute([]byte)mem.Raw_Slice{data, len}
  109. return read(fd, s)
  110. }
  111. heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
  112. size, alignment: int,
  113. old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, mem.Allocator_Error) {
  114. //
  115. // NOTE(tetra, 2020-01-14): The heap doesn't respect alignment.
  116. // Instead, we overallocate by `alignment + size_of(rawptr) - 1`, and insert
  117. // padding. We also store the original pointer returned by heap_alloc right before
  118. // the pointer we return to the user.
  119. //
  120. aligned_alloc :: proc(size, alignment: int, old_ptr: rawptr = nil) -> ([]byte, mem.Allocator_Error) {
  121. a := max(alignment, align_of(rawptr))
  122. space := size + a - 1
  123. allocated_mem: rawptr
  124. if old_ptr != nil {
  125. original_old_ptr := mem.ptr_offset((^rawptr)(old_ptr), -1)^
  126. allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr))
  127. } else {
  128. allocated_mem = heap_alloc(space+size_of(rawptr))
  129. }
  130. aligned_mem := rawptr(mem.ptr_offset((^u8)(allocated_mem), size_of(rawptr)))
  131. ptr := uintptr(aligned_mem)
  132. aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
  133. diff := int(aligned_ptr - ptr)
  134. if (size + diff) > space {
  135. return nil, .Out_Of_Memory
  136. }
  137. aligned_mem = rawptr(aligned_ptr)
  138. mem.ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem
  139. return mem.byte_slice(aligned_mem, size), nil
  140. }
  141. aligned_free :: proc(p: rawptr) {
  142. if p != nil {
  143. heap_free(mem.ptr_offset((^rawptr)(p), -1)^)
  144. }
  145. }
  146. aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int) -> ([]byte, mem.Allocator_Error) {
  147. if p == nil {
  148. return nil, nil
  149. }
  150. return aligned_alloc(new_size, new_alignment, p)
  151. }
  152. switch mode {
  153. case .Alloc:
  154. return aligned_alloc(size, alignment)
  155. case .Free:
  156. aligned_free(old_memory)
  157. case .Free_All:
  158. return nil, .Mode_Not_Implemented
  159. case .Resize:
  160. if old_memory == nil {
  161. return aligned_alloc(size, alignment)
  162. }
  163. return aligned_resize(old_memory, old_size, size, alignment)
  164. case .Query_Features:
  165. set := (^mem.Allocator_Mode_Set)(old_memory)
  166. if set != nil {
  167. set^ = {.Alloc, .Free, .Resize, .Query_Features}
  168. }
  169. return nil, nil
  170. case .Query_Info:
  171. return nil, .Mode_Not_Implemented
  172. }
  173. return nil, nil
  174. }
  175. heap_allocator :: proc() -> mem.Allocator {
  176. return mem.Allocator{
  177. procedure = heap_allocator_proc,
  178. data = nil,
  179. }
  180. }