1 /* 2 index: frame index data structure and functions 3 4 copyright 2007-2015 by the mpg123 project 5 -= free software under the terms of the LGPL 2.1 =- 6 see COPYING and AUTHORS files in distribution or http://mpg123.org 7 initially written by Thomas Orgis 8 */ 9 10 #include "intsym.h" 11 #include "index.h" 12 #include "debug.h" 13 14 /* The next expected frame offset, one step ahead. */ 15 static off_t fi_next(struct frame_index *fi) 16 { 17 return (off_t)fi->fill*fi->step; 18 } 19 20 /* Shrink down the used index to the half. 21 Be careful with size = 1 ... there's no shrinking possible there. */ 22 static void fi_shrink(struct frame_index *fi) 23 { 24 if(fi->fill < 2) return; /* Won't shrink below 1. */ 25 else 26 { /* Double the step, half the fill. Should work as well for fill%2 = 1 */ 27 size_t c; 28 debug2("shrink index with fill %lu and step %lu", (unsigned long)fi->fill, (unsigned long)fi->step); 29 fi->step *= 2; 30 fi->fill /= 2; 31 /* Move the data down. */ 32 for(c = 0; c < fi->fill; ++c) 33 fi->data[c] = fi->data[2*c]; 34 } 35 36 fi->next = fi_next(fi); 37 } 38 39 void fi_init(struct frame_index *fi) 40 { 41 fi->data = NULL; 42 fi->step = 1; 43 fi->fill = 0; 44 fi->size = 0; 45 fi->grow_size = 0; 46 fi->next = fi_next(fi); 47 } 48 49 void fi_exit(struct frame_index *fi) 50 { 51 debug2("fi_exit: %p and %lu", (void*)fi->data, (unsigned long)fi->size); 52 if(fi->size && fi->data != NULL) free(fi->data); 53 54 fi_init(fi); /* Be prepared for further fun, still. */ 55 } 56 57 int fi_resize(struct frame_index *fi, size_t newsize) 58 { 59 off_t *newdata = NULL; 60 if(newsize == fi->size) return 0; 61 62 if(newsize > 0 && newsize < fi->size) 63 { /* When we reduce buffer size a bit, shrink stuff. */ 64 while(fi->fill > newsize){ fi_shrink(fi); } 65 } 66 67 newdata = safe_realloc(fi->data, newsize*sizeof(off_t)); 68 if(newsize == 0 || newdata != NULL) 69 { 70 fi->data = newdata; 71 fi->size = newsize; 72 if(fi->fill > fi->size) fi->fill = fi->size; 73 74 fi->next = fi_next(fi); 75 debug2("new index of size %lu at %p", (unsigned long)fi->size, (void*)fi->data); 76 return 0; 77 } 78 else 79 { 80 error("failed to resize index!"); 81 return -1; 82 } 83 } 84 85 void fi_add(struct frame_index *fi, off_t pos) 86 { 87 debug3("wanting to add to fill %lu, step %lu, size %lu", (unsigned long)fi->fill, (unsigned long)fi->step, (unsigned long)fi->size); 88 if(fi->fill == fi->size) 89 { /* Index is full, we need to shrink... or grow. */ 90 /* Store the current frame number to check later if we still want it. */ 91 off_t framenum = fi->fill*fi->step; 92 /* If we want not / cannot grow, we shrink. */ 93 if( !(fi->grow_size && fi_resize(fi, fi->size+fi->grow_size)==0) ) 94 fi_shrink(fi); 95 96 /* Now check if we still want to add this frame (could be that not, because of changed step). */ 97 if(fi->next != framenum) return; 98 } 99 /* When we are here, we want that frame. */ 100 if(fi->fill < fi->size) /* safeguard for size=1, or just generally */ 101 { 102 debug1("adding to index at %p", (void*)(fi->data+fi->fill)); 103 fi->data[fi->fill] = pos; 104 ++fi->fill; 105 fi->next = fi_next(fi); 106 debug3("added pos %li to index with fill %lu and step %lu", (long) pos, (unsigned long)fi->fill, (unsigned long)fi->step); 107 } 108 } 109 110 int fi_set(struct frame_index *fi, off_t *offsets, off_t step, size_t fill) 111 { 112 if(fi_resize(fi, fill) == -1) return -1; 113 fi->step = step; 114 if(offsets != NULL) 115 { 116 memcpy(fi->data, offsets, fill*sizeof(off_t)); 117 fi->fill = fill; 118 } 119 else 120 { 121 /* allocation only, no entries in index yet */ 122 fi->fill = 0; 123 } 124 fi->next = fi_next(fi); 125 debug3("set new index of fill %lu, size %lu at %p", 126 (unsigned long)fi->fill, (unsigned long)fi->size, (void*)fi->data); 127 return 0; 128 } 129 130 void fi_reset(struct frame_index *fi) 131 { 132 debug1("reset with size %"SIZE_P, (size_p)fi->size); 133 fi->fill = 0; 134 fi->step = 1; 135 fi->next = fi_next(fi); 136 } 137