Sirikata
|
00001 /* Sirikata Transfer -- Content Transfer management system 00002 * Range.hpp 00003 * 00004 * Copyright (c) 2008, Patrick Reiter Horn 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions are 00009 * met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in 00014 * the documentation and/or other materials provided with the 00015 * distribution. 00016 * * Neither the name of Sirikata nor the names of its contributors may 00017 * be used to endorse or promote products derived from this software 00018 * without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00021 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00022 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00023 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00024 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 */ 00032 00033 #ifndef SIRIKATA_Range_HPP__ 00034 #define SIRIKATA_Range_HPP__ 00035 00036 namespace Sirikata { 00037 namespace Transfer { 00038 00039 typedef uint64 cache_usize_type; 00040 typedef int64 cache_ssize_type; 00041 00042 enum Initializer { LENGTH, BOUNDS }; 00043 00045 class Range { 00046 public: 00047 typedef cache_usize_type base_type; 00048 typedef cache_usize_type length_type; 00049 00050 typedef length_type size_type; 00051 typedef cache_ssize_type difference_type; 00052 00053 //static const length_type npos = (cache_usize_type)-1; 00054 private: 00056 base_type mStart; 00058 length_type mLength; 00059 00060 bool mWholeFile; 00061 00063 Range(base_type start, base_type end); 00064 public: 00065 00067 explicit Range(bool wholeFile) 00068 : mStart(0), mLength(0), mWholeFile(wholeFile) { 00069 } 00070 00072 Range(base_type start, bool wholeFile) 00073 : mStart(start), mLength(0), mWholeFile(wholeFile) { 00074 } 00075 00081 Range(base_type start, base_type length, 00082 Initializer type, bool wholeFile=false) 00083 : mStart(start), mLength(type==LENGTH?length:length-start), mWholeFile(wholeFile) { 00084 } 00085 00087 Range(const Range &other) 00088 : mStart(other.mStart), mLength(other.mLength), mWholeFile(other.mWholeFile) { 00089 } 00090 00095 inline bool goesToEndOfFile() const { 00096 return mWholeFile; 00097 } 00098 00100 inline base_type startbyte() const { 00101 return mStart; 00102 } 00107 inline length_type length() const { 00108 return mLength; 00109 } 00110 inline length_type size() const { 00111 return length(); 00112 } 00113 00115 inline base_type endbyte() const { 00116 return mStart + mLength - 1; 00117 } 00118 00120 inline void setLength(length_type l, bool wholeFile) { 00121 mLength = l; 00122 mWholeFile = wholeFile; 00123 } 00125 inline void setBase(base_type s) { 00126 mStart = s; 00127 } 00128 00130 inline bool operator< (const Range &other) const { 00131 if (mLength == other.mLength) { 00132 if (mStart == other.mStart && (mWholeFile || other.mWholeFile)) { 00133 return other.mWholeFile && !mWholeFile; 00134 } 00135 return mStart < other.mStart; 00136 } 00137 return mLength < other.mLength; 00138 } 00139 00146 friend inline std::ostream &operator << (std::ostream &os, const Range &range) { 00147 os << "[" << range.startbyte(); 00148 if (range.mLength) { 00149 os << ", " << range.endbyte(); 00150 } 00151 if (range.mWholeFile) { 00152 os << " => eof"; 00153 } 00154 os << ")"; 00155 return os; 00156 } 00157 00160 template <class ListType> 00161 bool isContainedBy(const ListType &list) const { 00162 00163 typename ListType::const_iterator iter = list.begin(), 00164 enditer = list.end(); 00165 00166 bool found = false; 00167 base_type lastEnd = 0; 00168 00169 while (iter != enditer) { 00170 base_type start = (*iter).startbyte(); 00171 if (mStart >= start && (*iter).goesToEndOfFile()) { 00172 return true; 00173 } 00174 base_type end = (*iter).endbyte(); 00175 00176 if (mStart >= start && mStart <= end) { 00177 found = true; 00178 lastEnd = end; 00179 break; 00180 } 00181 ++iter; 00182 } 00183 if (!found) { 00184 return false; 00185 } 00186 found = false; 00187 while (iter != enditer) { 00188 base_type start = (*iter).startbyte(); 00189 if (start > lastEnd) { 00190 found = false; // gap in range. 00191 break; 00192 } 00193 base_type end = (*iter).endbyte(); 00194 00195 // only an infinite range can include an infinite range. 00196 if ((*iter).goesToEndOfFile()) { 00197 return true; 00198 } 00199 if (!goesToEndOfFile() && endbyte() <= end) { 00200 found = true; 00201 break; 00202 } 00203 lastEnd = end; 00204 ++iter; 00205 } 00206 return found; 00207 } 00208 00209 inline bool contains(const Range &other) const { 00210 if (this->goesToEndOfFile()) { 00211 // endbyte infinitely long -- can contain anything. 00212 return (other.startbyte() >= this->startbyte()); 00213 } else if (!this->goesToEndOfFile() && other.goesToEndOfFile()) { 00214 // endbyte is not infinite. 00215 return false; 00216 } else { 00217 return (other.startbyte() >= this->startbyte()) && 00218 (other.endbyte() <= this->endbyte()); 00219 } 00220 } 00221 00222 inline bool isContainedBy(const Range &other) const { 00223 return other.contains(*this); 00224 } 00225 00227 template <class ListType> 00228 void addToList(const typename ListType::value_type &data, ListType &list) const { 00229 if (length()<=0) { 00230 // Ensure that no dummy data will get added. Shouldn't get here. 00231 return; 00232 } 00233 if (startbyte()==0 && goesToEndOfFile()) { 00234 // favor a single chunk covering the whole file. 00235 list.clear(); 00236 list.insert(list.end(), data); 00237 return; 00238 } 00239 00240 typename ListType::iterator endIter=list.end(), iter=list.begin(); 00241 Range::base_type startdata = startbyte(); 00242 Range::base_type maxend = startdata; 00243 bool includeseof = false; 00244 while (iter != endIter) { 00245 // maxend is not relevant for ranges strictly above us. 00246 if ((*iter).startbyte() > startdata) { 00247 break; 00248 } 00249 if ((*iter).endbyte() > maxend) { 00250 maxend = (*iter).endbyte(); 00251 } 00252 if ((*iter).goesToEndOfFile()) { 00253 includeseof = true; 00254 } 00255 // we do not want to allow for more than one 00256 // range starting at the same start byte-- 00257 // If this is the case, one is guaranteed to overlap. 00258 if ((*iter).startbyte() >= startdata) { 00259 break; 00260 } 00261 ++iter; 00262 } 00263 if (includeseof || (maxend > endbyte() && !goesToEndOfFile())) { 00264 return; // already included by another range. 00265 } 00266 iter = list.insert(iter, data); 00267 ++iter; 00268 while (iter != endIter) { 00269 typename ListType::iterator nextIter = iter; 00270 ++nextIter; 00271 00272 if (goesToEndOfFile() || 00273 (!(*iter).goesToEndOfFile() && (*iter).endbyte() <= endbyte())) { 00274 list.erase(iter); 00275 } 00276 00277 iter = nextIter; 00278 } 00279 } 00280 00281 template <class ListType> 00282 static std::ostream &printRangeList( 00283 std::ostream &os, 00284 const ListType &cdata, 00285 Range checkFor=Range(false), 00286 bool exact=false) { 00287 bool start = true; 00288 typename ListType::const_iterator iter = cdata.begin(), 00289 enditer = cdata.end(); 00290 for (; 00291 iter != enditer; 00292 ++iter) { 00293 os << (start?'{':',') << (*iter); 00294 start = false; 00295 if ((Range)(*iter) == checkFor) { 00296 os << "**"; 00297 } 00298 else if (!exact) { 00299 if ((*iter).isContainedBy(checkFor)) { 00300 os << "++"; 00301 } 00302 } 00303 } 00304 os << '}'; 00305 return os; 00306 } 00307 00309 inline bool operator== (const Range &other) const { 00310 return mLength == other.mLength && 00311 mStart == other.mStart && 00312 mWholeFile == other.mWholeFile; 00313 } 00314 }; 00315 00317 typedef std::list<Range> RangeList; 00318 00319 } 00320 } 00321 00322 #endif