log_allocator.odin 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package log
  2. import "base:runtime"
  3. import "core:fmt"
  4. Log_Allocator_Format :: enum {
  5. Bytes, // Actual number of bytes.
  6. Human, // Bytes in human units like bytes, kibibytes, etc. as appropriate.
  7. }
  8. Log_Allocator :: struct {
  9. allocator: runtime.Allocator,
  10. level: Level,
  11. prefix: string,
  12. locked: bool,
  13. size_fmt: Log_Allocator_Format,
  14. }
  15. log_allocator_init :: proc(la: ^Log_Allocator, level: Level, size_fmt := Log_Allocator_Format.Bytes,
  16. allocator := context.allocator, prefix := "") {
  17. la.allocator = allocator
  18. la.level = level
  19. la.prefix = prefix
  20. la.locked = false
  21. la.size_fmt = size_fmt
  22. }
  23. log_allocator :: proc(la: ^Log_Allocator) -> runtime.Allocator {
  24. return runtime.Allocator{
  25. procedure = log_allocator_proc,
  26. data = la,
  27. }
  28. }
  29. log_allocator_proc :: proc(allocator_data: rawptr, mode: runtime.Allocator_Mode,
  30. size, alignment: int,
  31. old_memory: rawptr, old_size: int, location := #caller_location) -> ([]byte, runtime.Allocator_Error) {
  32. la := (^Log_Allocator)(allocator_data)
  33. if context.logger.procedure == nil || la.level < context.logger.lowest_level {
  34. return la.allocator.procedure(la.allocator.data, mode, size, alignment, old_memory, old_size, location)
  35. }
  36. padding := " " if la.prefix != "" else ""
  37. buf: [256]byte = ---
  38. if !la.locked {
  39. la.locked = true
  40. defer la.locked = false
  41. switch mode {
  42. case .Alloc:
  43. format: string
  44. switch la.size_fmt {
  45. case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%d, alignment=%d)"
  46. case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc, size=%m, alignment=%d)"
  47. }
  48. str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment)
  49. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  50. case .Alloc_Non_Zeroed:
  51. format: string
  52. switch la.size_fmt {
  53. case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%d, alignment=%d)"
  54. case .Human: format = "%s%s>>> ALLOCATOR(mode=.Alloc_Non_Zeroed, size=%m, alignment=%d)"
  55. }
  56. str := fmt.bprintf(buf[:], format, la.prefix, padding, size, alignment)
  57. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  58. case .Free:
  59. if old_size != 0 {
  60. format: string
  61. switch la.size_fmt {
  62. case .Bytes: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%d)"
  63. case .Human: format = "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p, size=%m)"
  64. }
  65. str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size)
  66. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  67. } else {
  68. str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free, ptr=%p)", la.prefix, padding, old_memory)
  69. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  70. }
  71. case .Free_All:
  72. str := fmt.bprintf(buf[:], "%s%s<<< ALLOCATOR(mode=.Free_All)", la.prefix, padding)
  73. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  74. case .Resize:
  75. format: string
  76. switch la.size_fmt {
  77. case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%d, size=%d, alignment=%d)"
  78. case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize, ptr=%p, old_size=%m, size=%m, alignment=%d)"
  79. }
  80. str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
  81. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  82. case .Resize_Non_Zeroed:
  83. format: string
  84. switch la.size_fmt {
  85. case .Bytes: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%d, size=%d, alignment=%d)"
  86. case .Human: format = "%s%s>>> ALLOCATOR(mode=.Resize_Non_Zeroed, ptr=%p, old_size=%m, size=%m, alignment=%d)"
  87. }
  88. str := fmt.bprintf(buf[:], format, la.prefix, padding, old_memory, old_size, size, alignment)
  89. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  90. case .Query_Features:
  91. str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Features)", la.prefix, padding)
  92. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  93. case .Query_Info:
  94. str := fmt.bprintf(buf[:], "%s%sALLOCATOR(mode=.Query_Info)", la.prefix, padding)
  95. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  96. }
  97. }
  98. data, err := la.allocator.procedure(la.allocator.data, mode, size, alignment, old_memory, old_size, location)
  99. if !la.locked {
  100. la.locked = true
  101. defer la.locked = false
  102. if err != nil {
  103. str := fmt.bprintf(buf[:], "%s%sALLOCATOR ERROR=%v", la.prefix, padding, err)
  104. context.logger.procedure(context.logger.data, la.level, str, context.logger.options, location)
  105. }
  106. }
  107. return data, err
  108. }