Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_wroot_free_seg 5 #define tools_wroot_free_seg 6 7 #include "seek" 8 #include "wbuf" 9 #include "../forit" 10 11 #include <ostream> 12 13 namespace tools { 14 namespace wroot { 15 16 class free_seg { 17 public: 18 free_seg(std::ostream& a_out,seek a_first,seek a_last) 19 :m_out(a_out),m_first(a_first),m_last(a_last){} 20 virtual ~free_seg(){} 21 public: 22 free_seg(const free_seg& a_from) 23 :m_out(a_from.m_out),m_first(a_from.m_first),m_last(a_from.m_last) 24 {} 25 free_seg& operator=(const free_seg& a_from){ 26 m_first = a_from.m_first; 27 m_last = a_from.m_last; 28 return *this; 29 } 30 public: 31 std::ostream& out() const {return m_out;} 32 33 seek first() const {return m_first;} 34 seek last() const {return m_last;} 35 36 void set_first(seek a_v) {m_first = a_v;} 37 void set_last(seek a_v) {m_last = a_v;} 38 39 unsigned int record_size() const { 40 //GB if(fLast>RIO_START_BIG_FILE) { 41 if((m_first>START_BIG_FILE())|| //GB 42 (m_last>START_BIG_FILE()) ){ 43 return sizeof(short) + 2 * sizeof(seek); 44 } else { 45 return sizeof(short) + 2 * sizeof(seek32); 46 } 47 } 48 49 bool fill_buffer(wbuf& a_wb) { 50 short version = 1; 51 52 //GB if(fLast>START_BIG_FILE()) version += big_file_version_tag(); 53 if((m_first>START_BIG_FILE())|| 54 (m_last>START_BIG_FILE())) version += big_file_version_tag(); 55 56 if(!a_wb.write(version)) return false; 57 58 if(version>(short)big_file_version_tag()) { 59 if(!a_wb.write(m_first)) return false; 60 if(!a_wb.write(m_last)) return false; 61 } else { 62 if(m_first>START_BIG_FILE()) { //GB 63 m_out << "tools::wroot::free_seg::fill_buffer :" 64 << " attempt to write big Seek " 65 << m_first << " on 32 bits." 66 << std::endl; 67 return false; 68 } 69 if(!a_wb.write((seek32)m_first)) return false; 70 if(m_last>START_BIG_FILE()) { //GB 71 m_out << "tools::wroot::free_seg::fill_buffer :" 72 << " attempt to write big seek " 73 << m_last << " on 32 bits." 74 << std::endl; 75 return false; 76 } 77 if(!a_wb.write((seek32)m_last)) return false; 78 } 79 80 return true; 81 } 82 83 protected: 84 std::ostream& m_out; 85 seek m_first; //First free word of segment 86 seek m_last; //Last free word of segment 87 }; 88 89 }} 90 91 #include <list> 92 93 namespace tools { 94 namespace wroot { 95 96 inline free_seg* find_after(const std::list<free_seg*>& a_list,free_seg* a_what) { 97 tools_lforcit(free_seg*,a_list,it) { 98 if((*it)==a_what) { 99 it++; 100 if(it==a_list.end()) return 0; 101 return *it; 102 } 103 } 104 return 0; 105 } 106 107 inline void remove(std::list<free_seg*>& a_list,free_seg* a_what) { 108 //NOTE : it does not delete a_what. 109 tools_lforit(free_seg*,a_list,it) { 110 if((*it)==a_what) { 111 a_list.erase(it); 112 return; 113 } 114 } 115 } 116 117 inline void add_before(std::list<free_seg*>& a_list,free_seg* a_what,free_seg* a_new) { 118 tools_lforit(free_seg*,a_list,it) { 119 if((*it)==a_what) { 120 a_list.insert(it,a_new); 121 return; 122 } 123 } 124 } 125 126 inline free_seg* add_free(std::list<free_seg*>& a_list,seek a_first,seek a_last) { 127 // Add a new free segment to the list of free segments 128 // =================================================== 129 // If last just preceedes an existing free segment, then first becomes 130 // the new starting location of the free segment. 131 // if first just follows an existing free segment, then last becomes 132 // the new ending location of the free segment. 133 // if first just follows an existing free segment AND last just preceedes 134 // an existing free segment, these two segments are merged into 135 // one single segment. 136 // 137 138 free_seg* idcur = a_list.front(); 139 140 while (idcur) { 141 seek curfirst = idcur->first(); 142 seek curlast = idcur->last(); 143 if (curlast == (a_first-1)) { 144 idcur->set_last(a_last); 145 free_seg* idnext = find_after(a_list,idcur); 146 if (idnext == 0) return idcur; 147 if (idnext->first() > (a_last+1)) return idcur; 148 idcur->set_last(idnext->last()); 149 remove(a_list,idnext); //idnext not deleted. 150 delete idnext; 151 return idcur; 152 } 153 if (curfirst == (a_last+1)) { 154 idcur->set_first(a_first); 155 return idcur; 156 } 157 if (a_first < curfirst) { 158 free_seg* newfree = new free_seg(idcur->out(),a_first,a_last); 159 add_before(a_list,idcur,newfree); 160 return newfree; 161 } 162 idcur = find_after(a_list,idcur); 163 } 164 165 return 0; 166 } 167 168 169 }} 170 171 #endif