#define i64_MAX 0x7FFFFFFFFFFFFFFF
#define u64_MAX 0xFFFFFFFFFFFFFFFF
+#define PAD_TO_4( X ) (((u32)X+0x3) & ~(u32)0x3)
+#define PAD_TO_8( X ) (((u32)X+0x7) & ~(u32)0x7)
+#define PAD_TO_16( X ) (((u32)X+0xf) & ~(u32)0xf)
+
static inline f32 f32_min( f32 a, f32 b ){ return a < b? a: b; }
static inline f32 f32_max( f32 a, f32 b ){ return a > b? a: b; }
static inline i32 i32_min( i32 a, i32 b ){ return a < b? a: b; }
+void queue_init( struct queue_allocator *queue, void *buffer, u32 buffer_size )
+{
+ queue->buffer = buffer;
+ queue->size = buffer_size;
+ queue->head_offset = 0;
+ queue->tail_offset = 0;
+ queue->allocation_count = 0;
+}
+
+void *queue_alloc( struct queue_allocator *queue, u32 size )
+{
+ u32 total = PAD_TO_8(size) + sizeof( struct queue_item );
+ if( total > queue->size )
+ return NULL;
+
+ u32 prev_size = 0;
+ u32 new_item_offset;
+ if( queue->allocation_count )
+ {
+ struct queue_item *head = queue->buffer + queue->head_offset;
+ u32 end = queue->head_offset + head->alloc_size,
+ start = queue->tail_offset,
+ r0 = 0,
+ r1 = 0;
+ if( start < end )
+ {
+ r0 = queue->size - end;
+ r1 = start;
+ }
+ else
+ r0 = start - end;
+
+ if( total < r0 )
+ new_item_offset = end;
+ else
+ {
+ if( total < r1 )
+ {
+ head->alloc_size += r0;
+ new_item_offset = 0;
+ }
+ else
+ {
+ /* Full */
+ return NULL;
+ }
+ }
+
+ prev_size = head->alloc_size;
+ }
+ else
+ {
+ new_item_offset = 0;
+ queue->tail_offset = 0;
+ }
+
+ struct queue_item *item = (struct queue_item *)(queue->buffer + new_item_offset);
+ zero_buffer( item, sizeof(struct queue_item) );
+ item->alloc_size = total;
+ item->prev_size = prev_size;
+
+ queue->head_offset = new_item_offset;
+ queue->allocation_count ++;
+ return item->data;
+}
+
+void *queue_data( struct queue_allocator *queue, u32 offset )
+{
+ return queue->buffer + offset;
+}
+
+void *queue_tail_data( struct queue_allocator *queue )
+{
+ if( queue->allocation_count ) return queue_data( queue, queue->tail_offset );
+ else return NULL;
+}
+
+u32 queue_offset( struct queue_allocator *queue, void *pointer )
+{
+ return pointer - queue->buffer;
+}
+
+u32 queue_item_size( struct queue_allocator *queue, u32 item_id )
+{
+ struct queue_item *item = queue->buffer + item_id;
+ return item->alloc_size;
+}
+
+bool queue_next( struct queue_allocator *queue, u32 item_id, u32 *out_next )
+{
+ if( item_id != queue->head_offset )
+ {
+ struct queue_item *item = queue->buffer + item_id;
+ if( item_id + item->alloc_size == queue->size ) *out_next = 0;
+ else *out_next = item_id + item->alloc_size;
+ return 1;
+ }
+ else return 0;
+}
+
+bool queue_previous( struct queue_allocator *queue, u32 item_id, u32 *out_prev )
+{
+ struct queue_item *item = queue->buffer + item_id;
+ if( item_id != queue->tail_offset )
+ {
+ if( item_id == 0 ) *out_prev = queue->size - item->prev_size;
+ else *out_prev = item_id - item->prev_size;
+ return 1;
+ }
+ else return 0;
+}
+
+void queue_pop( struct queue_allocator *queue )
+{
+ ASSERT_CRITICAL( queue->allocation_count );
+ queue->allocation_count --;
+
+ if( queue->allocation_count == 0 )
+ {
+ queue->head_offset = 0;
+ queue->tail_offset = 0;
+ return;
+ }
+
+ struct queue_item *tail = queue->buffer + queue->tail_offset;
+ u32 start = queue->tail_offset + tail->alloc_size;
+
+ if( start == queue->size )
+ start = 0;
+
+ queue->tail_offset = start;
+ tail = queue->buffer + queue->tail_offset;
+ tail->prev_size = 0;
+}
+
+void queue_copy_buffer( struct queue_allocator *queue, void *dst, u32 start, u32 size )
+{
+ if( start + size > queue->size )
+ {
+ u32 r0 = queue->size - start;
+ buffer_copy( queue->buffer + start, r0, dst, r0 );
+ buffer_copy( queue->buffer, size-r0, dst+r0, size-r0 );
+ }
+ else
+ buffer_copy( queue->buffer + start, size, dst, size );
+}
+
+u32 queue_usage( struct queue_allocator *queue )
+{
+ if( queue->allocation_count )
+ {
+ struct queue_item *head = queue->buffer + queue->head_offset;
+ u32 end = queue->head_offset + head->alloc_size,
+ start = queue->tail_offset;
+ if( start < end )
+ return end - start;
+ else
+ return (queue->size - start) + end;
+ }
+ else
+ return 0;
+}
+
+void queue_clear( struct queue_allocator *queue )
+{
+ queue->head_offset = 0;
+ queue->tail_offset = 0;
+ queue->allocation_count = 0;
+}
+++ /dev/null
-void vg_queue_memcpy( vg_queue *q, void *dst, u32 start, u32 size )
-{
- if( start + size > q->size )
- {
- u32 r0 = q->size - start;
- memcpy( dst, q->buffer + start, r0 );
- memcpy( dst+r0, q->buffer, size-r0 );
- }
- else
- memcpy( dst, q->buffer + start, size );
-}
-
-void *vg_queue_data( vg_queue *q, u32 offset )
-{
- vg_queue_item *item = q->buffer + offset;
- return item->data;
-}
-
-void *vg_queue_tail_data( vg_queue *q )
-{
- if( q->allocation_count ) return vg_queue_data( q, q->tail_offset );
- else return NULL;
-}
-
-u32 vg_queue_offset( vg_queue *q, void *pointer )
-{
- return pointer - q->buffer;
-}
-
-void *vg_queue_pointer( vg_queue *q, u32 offset )
-{
- return q->buffer + offset;
-}
-
-/*
- * Allocate memory on the queue. Returns NULL if allocation failed for any reason
- */
-void *vg_queue_alloc( vg_queue *q, u32 size )
-{
- u32 total = vg_align8(size) + sizeof(vg_queue_item);
- if( total > q->size )
- return NULL;
-
- u32 prev_size = 0;
- u32 new_item_offset;
- if( q->allocation_count )
- {
- vg_queue_item *head = q->buffer + q->head_offset;
- u32 end = q->head_offset + head->alloc_size,
- start = q->tail_offset,
- r0 = 0,
- r1 = 0;
-
- if( start < end )
- {
- r0 = q->size - end;
- r1 = start;
- }
- else
- r0 = start - end;
-
- if( total < r0 )
- new_item_offset = end;
- else
- {
- if( total < r1 )
- {
- head->alloc_size += r0;
- new_item_offset = 0;
- }
- else
- {
- /* Full */
- return NULL;
- }
- }
-
- prev_size = head->alloc_size;
- }
- else
- {
- new_item_offset = 0;
- q->tail_offset = 0;
- }
-
- vg_queue_item *item = (vg_queue_item *)(q->buffer + new_item_offset);
- vg_zero_mem( item, sizeof(vg_queue_item) );
- item->alloc_size = total;
- item->prev_size = prev_size;
-
- q->head_offset = new_item_offset;
- q->allocation_count ++;
- return item->data;
-}
-
-/*
- * Free last item from queue
- */
-void vg_queue_pop( vg_queue *q )
-{
- VG_ASSERT( q->allocation_count );
- q->allocation_count --;
-
- if( q->allocation_count == 0 )
- {
- q->head_offset = 0;
- q->tail_offset = 0;
- return;
- }
-
- vg_queue_item *tail = q->buffer + q->tail_offset;
- u32 start = q->tail_offset + tail->alloc_size;
-
- if( start == q->size )
- start = 0;
-
- q->tail_offset = start;
-
- tail = q->buffer + q->tail_offset;
- tail->prev_size = 0;
-}
-
-u32 vg_queue_item_size( vg_queue *q, u32 item_id )
-{
- vg_queue_item *item = q->buffer + item_id;
- return item->alloc_size;
-}
-
-bool vg_queue_previous( vg_queue *q, u32 item_id, u32 *out_prev )
-{
- vg_queue_item *item = q->buffer + item_id;
- if( item_id != q->tail_offset )
- {
- if( item_id == 0 ) *out_prev = q->size - item->prev_size;
- else *out_prev = item_id - item->prev_size;
- return 1;
- }
- else return 0;
-}
-
-bool vg_queue_next( vg_queue *q, u32 item_id, u32 *out_next )
-{
- if( item_id != q->head_offset )
- {
- vg_queue_item *item = q->buffer + item_id;
- if( item_id + item->alloc_size == q->size ) *out_next = 0;
- else *out_next = item_id + item->alloc_size;
- return 1;
- }
- else return 0;
-}
-
-u32 vg_queue_usage( vg_queue *q )
-{
- if( q->allocation_count )
- {
- vg_queue_item *head = q->buffer + q->head_offset;
- u32 end = q->head_offset + head->alloc_size,
- start = q->tail_offset;
-
- if( start < end )
- return end - start;
- else
- return (q->size - start) + end;
- }
- else
- return 0;
-}
-
-void vg_queue_clear( vg_queue *q )
-{
- q->head_offset = 0;
- q->tail_offset = 0;
- q->allocation_count = 0;
-}
+++ /dev/null
-#if defined( VG_IMPLEMENTATION )
-# include "vg/vg_mem_queue.c"
-#else
-
-#define VG_MEM_QUEUE_INVALID 0xffffffff
-
-typedef struct vg_queue vg_queue;
-typedef struct vg_queue_item vg_queue_item;
-
-struct vg_queue_item
-{
- u32 alloc_size,prev_size;
- u8 data[];
-};
-
-struct vg_queue
-{
- void *buffer;
- u32 size;
- u32 head_offset, tail_offset;
- u32 allocation_count;
-};
-
-void *vg_queue_alloc( vg_queue *q, u32 size );
-
-void *vg_queue_data( vg_queue *q, u32 offset );
-void *vg_queue_tail_data( vg_queue *q );
-u32 vg_queue_offset( vg_queue *q, void *pointer );
-
-/* warning: this is not the size but the allocation size (may be padded) */
-u32 vg_queue_item_size( vg_queue *q, u32 item_id );
-bool vg_queue_next( vg_queue *q, u32 item_id, u32 *out_next );
-bool vg_queue_previous( vg_queue *q, u32 item_id, u32 *out_prev );
-void vg_queue_pop( vg_queue *q );
-void vg_queue_memcpy( vg_queue *q, void *dst, u32 start, u32 size );
-
-u32 vg_queue_usage( vg_queue *q );
-void vg_queue_clear( vg_queue *q );
-
-#endif