1 /* 2 index: frame index data structure and functions 3 4 copyright 2007-2020 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 } else 78 return -1; 79 } 80 81 void fi_add(struct frame_index *fi, off_t pos) 82 { 83 debug3("wanting to add to fill %lu, step %lu, size %lu", (unsigned long)fi->fill, (unsigned long)fi->step, (unsigned long)fi->size); 84 if(fi->fill == fi->size) 85 { /* Index is full, we need to shrink... or grow. */ 86 /* Store the current frame number to check later if we still want it. */ 87 off_t framenum = fi->fill*fi->step; 88 /* If we want not / cannot grow, we shrink. */ 89 if( !(fi->grow_size && fi_resize(fi, fi->size+fi->grow_size)==0) ) 90 fi_shrink(fi); 91 92 /* Now check if we still want to add this frame (could be that not, because of changed step). */ 93 if(fi->next != framenum) return; 94 } 95 /* When we are here, we want that frame. */ 96 if(fi->fill < fi->size) /* safeguard for size=1, or just generally */ 97 { 98 debug1("adding to index at %p", (void*)(fi->data+fi->fill)); 99 fi->data[fi->fill] = pos; 100 ++fi->fill; 101 fi->next = fi_next(fi); 102 debug3("added pos %li to index with fill %lu and step %lu", (long) pos, (unsigned long)fi->fill, (unsigned long)fi->step); 103 } 104 } 105 106 int fi_set(struct frame_index *fi, off_t *offsets, off_t step, size_t fill) 107 { 108 if(fi_resize(fi, fill) == -1) return -1; 109 fi->step = step; 110 if(offsets != NULL) 111 { 112 memcpy(fi->data, offsets, fill*sizeof(off_t)); 113 fi->fill = fill; 114 } 115 else 116 { 117 /* allocation only, no entries in index yet */ 118 fi->fill = 0; 119 } 120 fi->next = fi_next(fi); 121 debug3("set new index of fill %lu, size %lu at %p", 122 (unsigned long)fi->fill, (unsigned long)fi->size, (void*)fi->data); 123 return 0; 124 } 125 126 void fi_reset(struct frame_index *fi) 127 { 128 debug1("reset with size %"SIZE_P, (size_p)fi->size); 129 fi->fill = 0; 130 fi->step = 1; 131 fi->next = fi_next(fi); 132 } 133