1 /* 2 * ppui/PPPath.h 3 * 4 * Copyright 2009 Peter Barth 5 * 6 * This file is part of Milkytracker. 7 * 8 * Milkytracker is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * Milkytracker is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with Milkytracker. If not, see <http://www.gnu.org/licenses/>. 20 * 21 */ 22 23 /* 24 * PPPath.h 25 * MilkyTracker 26 * 27 * Created by Peter Barth on 12.10.06. 28 * 29 */ 30 31 #ifndef __PPPATH_H__ 32 #define __PPPATH_H__ 33 34 #include "BasicTypes.h" 35 36 class PPPathEntry 37 { 38 public: 39 enum Type 40 { 41 Nonexistent, 42 Hidden, 43 File, 44 Directory 45 }; 46 47 48 protected: 49 PPSystemString name; 50 Type type; 51 pp_uint32 size; 52 53 public: PPPathEntry()54 PPPathEntry() { } 55 ~PPPathEntry()56 virtual ~PPPathEntry() { } 57 create(const PPSystemString & path,const PPSystemString & name)58 virtual void create(const PPSystemString& path, const PPSystemString& name) 59 { 60 this->name = name; 61 type = Nonexistent; 62 size = 0; 63 } 64 getName()65 virtual const PPSystemString& getName() const { return name; } 66 isFile()67 virtual bool isFile() const { return type == File; } isDirectory()68 virtual bool isDirectory() const { return type == Directory; } getSize()69 virtual pp_uint32 getSize() const { return size; } isHidden()70 virtual bool isHidden() const { return type == Hidden; } isDrive()71 virtual bool isDrive() const { return false; } isParent()72 virtual bool isParent() const 73 { 74 static const PPSystemString temp(".."); 75 return name.compareTo(temp) == 0; 76 } 77 compareTo(const PPPathEntry & src)78 virtual bool compareTo(const PPPathEntry& src) const 79 { 80 if (name.compareTo(src.name) != 0) 81 return false; 82 83 return (type == src.type && size == src.size); 84 } 85 clone()86 virtual PPPathEntry* clone() const 87 { 88 // check if this is the correct type 89 PPPathEntry* result = new PPPathEntry(); 90 91 result->name = name; 92 result->type = type; 93 result->size = size; 94 95 return result; 96 } 97 98 class PathSortRuleInterface 99 { 100 public: 101 virtual pp_int32 compare(const PPPathEntry& left, const PPPathEntry& right) const = 0; 102 }; 103 104 class PathSortByFileRule : public PathSortRuleInterface 105 { 106 public: compare(const PPPathEntry & left,const PPPathEntry & right)107 virtual pp_int32 compare(const PPPathEntry& left, const PPPathEntry& right) const 108 { 109 // no drives 110 if (!left.isDrive() && !right.isDrive()) 111 { 112 if (left.isFile() && right.isFile()) 113 { 114 return left.getName().compareToNoCase(right.getName()); 115 } 116 else if (left.isDirectory() && right.isDirectory()) 117 { 118 if (!left.isParent() && !right.isParent()) 119 return left.getName().compareToNoCase(right.getName()); 120 else if (left.isParent()) 121 return -1; 122 else 123 return 1; 124 } 125 else 126 { 127 if (left.isDirectory() && right.isFile()) 128 return -1; 129 else 130 return 1; 131 } 132 } 133 // drives 134 else if (left.isDrive() && right.isDrive()) 135 { 136 return left.getName().compareToNoCase(right.getName()); 137 } 138 else 139 { 140 if (left.isDrive() && !right.isDrive()) 141 return 1; 142 else 143 return -1; 144 } 145 } 146 }; 147 148 class PathSortBySizeRule : public PathSortRuleInterface 149 { 150 public: compare(const PPPathEntry & left,const PPPathEntry & right)151 virtual pp_int32 compare(const PPPathEntry& left, const PPPathEntry& right) const 152 { 153 // both are files 154 if (!left.isDirectory() && !right.isDirectory()) 155 { 156 if (left.getSize() != right.getSize()) 157 return left.getSize() - right.getSize(); 158 else 159 return left.getName().compareToNoCase(right.getName()); 160 } 161 // directory 162 else if (left.isDirectory() && right.isDirectory()) 163 { 164 PathSortByFileRule comparator; 165 return comparator.compare(left, right); 166 } 167 else 168 { 169 if (left.isDirectory() && !right.isDirectory()) 170 return -1; 171 else 172 return 1; 173 } 174 } 175 }; 176 177 class PathSortByExtRule : public PathSortRuleInterface 178 { 179 public: compare(const PPPathEntry & left,const PPPathEntry & right)180 virtual pp_int32 compare(const PPPathEntry& left, const PPPathEntry& right) const 181 { 182 // both are files 183 if (!left.isDirectory() && !right.isDirectory()) 184 { 185 pp_int32 diff = left.getName().compareExtensions(right.getName()); 186 187 if (diff == 0) 188 return left.getName().compareToNoCase(right.getName()); 189 else 190 return diff; 191 } 192 // directory 193 else if (left.isDirectory() && right.isDirectory()) 194 { 195 PathSortByFileRule comparator; 196 return comparator.compare(left, right); 197 } 198 else 199 { 200 if (left.isDirectory() && !right.isDirectory()) 201 return -1; 202 else 203 return 1; 204 } 205 } 206 }; 207 208 private: 209 static pp_int32 partition(PPPathEntry** a, pp_int32 left, pp_int32 right, const PathSortRuleInterface& sortRule, bool descending = false) 210 { 211 const pp_int32 sign = descending ? -1 : 1; 212 213 pp_int32 first=left, pivot=right--; 214 while(left<=right) 215 { 216 while(sortRule.compare(*a[left], *a[pivot])*sign < 0/*a[left]<a[pivot]*/) 217 left++; 218 219 while((right>=first)&&(sortRule.compare(*a[right], *a[pivot])*sign >= 0/*a[right]>=a[pivot]*/)) 220 right--; 221 222 if(left<right) 223 { 224 swap(a, left,right); 225 left++; 226 } 227 } 228 if(left!=pivot) 229 swap(a, left,pivot); 230 231 return left; 232 } 233 swap(PPPathEntry ** a,pp_int32 i,pp_int32 j)234 static void swap(PPPathEntry** a, pp_int32 i, pp_int32 j) 235 { 236 PPPathEntry* temp=a[i]; 237 a[i]=a[j]; 238 a[j]=temp; 239 } 240 241 static void sortInternal(PPPathEntry** array, pp_int32 left, pp_int32 right, const PathSortRuleInterface& sortRule, bool descending = false) 242 { 243 pp_int32 p; 244 245 if(left>=right) 246 return; 247 248 p = partition(array, left, right, sortRule, descending); 249 250 sortInternal(array, left,p-1, sortRule, descending); 251 sortInternal(array, p+1, right, sortRule, descending); 252 253 /*const pp_int32 sign = descending ? -1 : 1; 254 pp_int32 i,j; 255 PPPathEntry* x; 256 PPPathEntry* y; 257 i=l; j=r; x=array[(l+r)/2]; 258 do 259 { 260 while (sortRule.compare(*array[i], *x)*sign < 0) i++; 261 while (sortRule.compare(*x, *array[j])*sign < 0 && j > 0) j--; 262 if (i <= j) 263 { 264 y=array[i]; array[i]=array[j]; array[j]=y; 265 i++; j--; 266 } 267 } while (i<=j); 268 if (l<j) sortInternal(array, l, j, sortRule, descending); 269 if (i<r) sortInternal(array, i, r, sortRule, descending);*/ 270 } 271 272 public: 273 static void sort(PPPathEntry** array, pp_int32 l, pp_int32 r, const PathSortRuleInterface& sortRule, bool descending = false) 274 { 275 // no need to sort 276 if (l == 0 && r <= 1) 277 return; 278 279 sortInternal(array, l, r, sortRule, descending); 280 } 281 282 }; 283 284 class PPPath 285 { 286 public: ~PPPath()287 virtual ~PPPath() {} 288 virtual const PPSystemString getCurrent() = 0; 289 290 virtual bool change(const PPSystemString& path) = 0; 291 virtual bool stepInto(const PPSystemString& directory) = 0; 292 293 virtual const PPPathEntry* getFirstEntry() = 0; 294 virtual const PPPathEntry* getNextEntry() = 0; 295 296 virtual bool canGotoHome() const = 0; 297 virtual void gotoHome() = 0; 298 virtual bool canGotoRoot() const = 0; 299 virtual void gotoRoot() = 0; 300 virtual bool canGotoParent() const = 0; 301 virtual void gotoParent() = 0; 302 303 virtual char getPathSeparatorAsASCII() const = 0; 304 virtual const PPSystemString getPathSeparator() const = 0; 305 306 virtual bool fileExists(const PPSystemString& fileName) const = 0; 307 }; 308 309 #endif 310 311 312