11const std = @import ("std" );
2+ const testing = std .testing ;
23const bgfx = @import ("bgfx" );
34const builtin = @import ("builtin" );
45
@@ -8,24 +9,87 @@ const Self = @This();
89
910//
1011// Allocator
11- // FIXME: Does not work because `panic: integer cast truncated bits` from true zig allocator.
1212//
1313
1414pub const CAllocInterfaceT = extern struct { vtable : * const CAllocVtblT };
1515pub const CAllocVtblT = extern struct {
16- realloc : * const fn (_this : * CAllocInterfaceT , _ptr : [* c ]u8 , _size : usize , _align : usize , _file : [* :0 ]const u8 , _line : u32 ) callconv (.c ) ? * anyopaque ,
16+ realloc : * const fn (_this : * CAllocInterfaceT , _ptr : [* c ]u8 , _size : usize , _align : usize , _file : [* :0 ]const u8 , _line : u32 ) callconv (.c ) [ * c ] u8 ,
1717};
1818
1919pub const ZigAllocatorVtbl = extern struct {
20- fn realloc (_this : * CAllocInterfaceT , _ptr : [* c ]u8 , _size : usize , _align : usize , _file : [* :0 ]const u8 , _line : u32 ) callconv (.c ) ? * anyopaque {
20+ fn realloc (_this : * CAllocInterfaceT , _ptr : [* c ]u8 , _size : usize , _align : usize , _file : [* :0 ]const u8 , _line : u32 ) callconv (.c ) [ * c ] u8 {
2121 var self : * ZigAllocator = @ptrCast (_this );
2222 _ = _file ; // autofix
2323 _ = _line ; // autofix
2424
25+ const alloc_align = ZigAllocator .getAllocationAlignment (_align );
26+ const alignment = std .mem .Alignment .fromByteUnits (alloc_align );
27+
2528 if (_size != 0 ) {
26- return self .allocator .rawAlloc (_size , @truncate (_align ), 0 );
29+ const alloc_size = ZigAllocator .getAllocationSize (_size , alloc_align );
30+
31+ if (_ptr ) | ptr | {
32+ // realloc
33+
34+ const base_ptr = ZigAllocator .getBasePointer (ptr , alloc_align );
35+ var header_ptr = ZigAllocator .getHeaderPointer (base_ptr );
36+
37+ const old_size = header_ptr .size ;
38+ const old_mem = base_ptr [0.. header_ptr .size ];
39+
40+ const new_mem = blk : {
41+ if (self .allocator .rawRemap (old_mem , alignment , alloc_size , @returnAddress ())) | mem | {
42+ break :blk mem [0.. alloc_size ];
43+ }
44+
45+ if (self .allocator .rawAlloc (alloc_size , alignment , @returnAddress ())) | mem | {
46+ const copy_size = @min (old_size , alloc_size );
47+ @memcpy (mem [0.. copy_size ], old_mem [0.. copy_size ]);
48+
49+ self .allocator .rawFree (old_mem , alignment , @returnAddress ());
50+
51+ break :blk mem [0.. alloc_size ];
52+ }
53+
54+ break :blk null ;
55+ };
56+
57+ if (new_mem ) | mem | {
58+ header_ptr = ZigAllocator .getHeaderPointer (mem .ptr );
59+ header_ptr .size = alloc_size ;
60+
61+ return ZigAllocator .getPayloadPointer (mem .ptr , alloc_align );
62+ }
63+
64+ return null ;
65+ } else {
66+ // alloc
67+
68+ const new_mem = if (self .allocator .rawAlloc (alloc_size , alignment , @returnAddress ())) | mem | mem [0.. alloc_size ] else null ;
69+
70+ if (new_mem ) | mem | {
71+ var header_ptr = ZigAllocator .getHeaderPointer (mem .ptr );
72+ header_ptr .size = alloc_size ;
73+
74+ return ZigAllocator .getPayloadPointer (mem .ptr , alloc_align );
75+ }
76+
77+ return null ;
78+ }
79+ } else if (_ptr ) | ptr | {
80+ // free
81+
82+ const base_ptr = ZigAllocator .getBasePointer (ptr , alloc_align );
83+ const header_ptr = ZigAllocator .getHeaderPointer (base_ptr );
84+
85+ const old_size = header_ptr .size ;
86+ const old_mem = base_ptr [0.. old_size ];
87+
88+ self .allocator .rawFree (old_mem , alignment , @returnAddress ());
89+
90+ return null ;
2791 }
28- self . allocator . free ( _ptr [0 .. _size ]);
92+
2993 return null ;
3094 }
3195 pub fn toVtbl () Self.CAllocVtblT {
@@ -36,13 +100,86 @@ pub const ZigAllocatorVtbl = extern struct {
36100pub const ZigAllocator = extern struct {
37101 const _alloc_vtable = ZigAllocatorVtbl .toVtbl ();
38102 vtable : ? * const CAllocVtblT = null ,
39- allocator : * std.mem.Allocator ,
103+ allocator : * const std.mem.Allocator ,
40104
41- pub fn init (alloc : * std.mem.Allocator ) ZigAllocator {
42- return .{ .vtable = & _alloc_vtable , .allocator = alloc };
105+ pub fn init (alloc : * const std.mem.Allocator ) ZigAllocator {
106+ return .{
107+ .vtable = & _alloc_vtable ,
108+ .allocator = alloc ,
109+ };
110+ }
111+
112+ const AllocationHeader = struct {
113+ size : usize ,
114+ };
115+
116+ pub fn getAllocationAlignment (_align : usize ) usize {
117+ return @max (_align , @alignOf (AllocationHeader ));
118+ }
119+
120+ pub fn getAllocationSize (_size : usize , _align : usize ) usize {
121+ return _size + @sizeOf (AllocationHeader ) + _align - 1 ;
122+ }
123+
124+ pub fn getPayloadPointer (_ptr : [* c ]u8 , _align : usize ) [* c ]u8 {
125+ return std .mem .alignForward (usize , @intFromPtr (_ptr ) + @sizeOf (AllocationHeader ), _align );
126+ }
127+
128+ pub fn getBasePointer (payload_ptr : [* c ]u8 , _align : usize ) [* c ]u8 {
129+ return std .mem .alignBackward (usize , @intFromPtr (payload_ptr ) - @sizeOf (AllocationHeader ), _align );
130+ }
131+
132+ pub fn getHeaderPointer (_ptr : [* c ]u8 ) * AllocationHeader {
133+ return @ptrCast (@alignCast (_ptr ));
43134 }
44135};
45136
137+ test "zig allocator" {
138+ var zig_alloc = ZigAllocator .init (& testing .allocator );
139+
140+ const realloc = zig_alloc .vtable .? .realloc ;
141+
142+ var _align : usize = 64 ;
143+
144+ var ptr = realloc (@ptrCast (& zig_alloc ), null , 100 * 1024 , _align , "" , 0 );
145+ try testing .expect (ptr != null );
146+ ptr [10 ] = 5 ;
147+
148+ ptr = realloc (@ptrCast (& zig_alloc ), ptr , 200 * 1024 , _align , "" , 0 );
149+ try testing .expect (ptr != null );
150+ try testing .expectEqual (5 , ptr [10 ]);
151+
152+ ptr = realloc (@ptrCast (& zig_alloc ), ptr , 50 , _align , "" , 0 );
153+ try testing .expect (ptr != null );
154+ try testing .expectEqual (5 , ptr [10 ]);
155+
156+ ptr = realloc (@ptrCast (& zig_alloc ), ptr , 0 , _align , "" , 0 );
157+ try testing .expect (ptr == null );
158+
159+ ptr = realloc (@ptrCast (& zig_alloc ), null , 0 , _align , "" , 0 );
160+ try testing .expect (ptr == null );
161+
162+ _align = 0 ;
163+
164+ ptr = realloc (@ptrCast (& zig_alloc ), null , 100 * 1024 , _align , "" , 0 );
165+ try testing .expect (ptr != null );
166+ ptr [10 ] = 5 ;
167+
168+ ptr = realloc (@ptrCast (& zig_alloc ), ptr , 200 * 1024 , _align , "" , 0 );
169+ try testing .expect (ptr != null );
170+ try testing .expectEqual (5 , ptr [10 ]);
171+
172+ ptr = realloc (@ptrCast (& zig_alloc ), ptr , 50 , _align , "" , 0 );
173+ try testing .expect (ptr != null );
174+ try testing .expectEqual (5 , ptr [10 ]);
175+
176+ ptr = realloc (@ptrCast (& zig_alloc ), ptr , 0 , _align , "" , 0 );
177+ try testing .expect (ptr == null );
178+
179+ ptr = realloc (@ptrCast (& zig_alloc ), null , 0 , _align , "" , 0 );
180+ try testing .expect (ptr == null );
181+ }
182+
46183//
47184// Callbacks
48185//
0 commit comments