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