Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/waysx.c
Parent Directory
|
Revision Log
Revision 213 -
(show annotations)
(download)
(as text)
Thu Jul 2 16:33:31 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 8890 byte(s)
Thu Jul 2 16:33:31 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 8890 byte(s)
Removed unused header files, change assert statements, tidy some code.
1 | /*************************************** |
2 | $Header: /home/amb/CVS/routino/src/waysx.c,v 1.9 2009-07-02 16:33:31 amb Exp $ |
3 | |
4 | Extended Way data type functions. |
5 | |
6 | Part of the Routino routing software. |
7 | ******************/ /****************** |
8 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | |
10 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by |
12 | the Free Software Foundation, either version 3 of the License, or |
13 | (at your option) any later version. |
14 | |
15 | This program is distributed in the hope that it will be useful, |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public License |
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | ***************************************/ |
23 | |
24 | |
25 | #include <assert.h> |
26 | #include <stdlib.h> |
27 | #include <string.h> |
28 | |
29 | #include "functions.h" |
30 | #include "waysx.h" |
31 | |
32 | |
33 | /* Constants */ |
34 | |
35 | /*+ The array size increment for ways - expect ~1,000,000 ways. +*/ |
36 | #define INCREMENT_WAYS 256*1024 |
37 | |
38 | |
39 | /* Functions */ |
40 | |
41 | static int sort_by_id(WayX **a,WayX **b); |
42 | static int sort_by_name_and_properties(WayX **a,WayX **b); |
43 | |
44 | |
45 | /*++++++++++++++++++++++++++++++++++++++ |
46 | Allocate a new way list. |
47 | |
48 | WaysX *NewWayList Returns the way list. |
49 | ++++++++++++++++++++++++++++++++++++++*/ |
50 | |
51 | WaysX *NewWayList(void) |
52 | { |
53 | WaysX *waysx; |
54 | |
55 | waysx=(WaysX*)calloc(1,sizeof(WaysX)); |
56 | |
57 | return(waysx); |
58 | } |
59 | |
60 | |
61 | /*++++++++++++++++++++++++++++++++++++++ |
62 | Save the way list to a file. |
63 | |
64 | WaysX* waysx The set of ways to save. |
65 | |
66 | const char *filename The name of the file to save. |
67 | ++++++++++++++++++++++++++++++++++++++*/ |
68 | |
69 | void SaveWayList(WaysX* waysx,const char *filename) |
70 | { |
71 | int i; |
72 | int fd; |
73 | Ways *ways=calloc(1,sizeof(Ways)); |
74 | |
75 | assert(waysx->sorted); /* Must be sorted */ |
76 | assert(waysx->wdata); /* Must have wdata filled in */ |
77 | |
78 | /* Fill in a Ways structure with the offset of the real data in the file after |
79 | the Way structure itself. */ |
80 | |
81 | ways->number=waysx->wnumber; |
82 | ways->data=NULL; |
83 | ways->ways=(void*)sizeof(Ways); |
84 | ways->names=(void*)sizeof(Ways)+ways->number*sizeof(Way); |
85 | |
86 | /* Write out the Ways structure and then the real data. */ |
87 | |
88 | fd=OpenFile(filename); |
89 | |
90 | WriteFile(fd,ways,sizeof(Ways)); |
91 | |
92 | for(i=0;i<ways->number;i++) |
93 | { |
94 | WriteFile(fd,&waysx->wdata[i],sizeof(Way)); |
95 | |
96 | if(!((i+1)%10000)) |
97 | { |
98 | printf("\rWriting Ways: Ways=%d",i+1); |
99 | fflush(stdout); |
100 | } |
101 | } |
102 | |
103 | printf("\rWrote Ways: Ways=%d \n",ways->number); |
104 | fflush(stdout); |
105 | |
106 | WriteFile(fd,waysx->names,waysx->length); |
107 | |
108 | CloseFile(fd); |
109 | |
110 | /* Free the fake Ways */ |
111 | |
112 | free(ways); |
113 | } |
114 | |
115 | |
116 | /*++++++++++++++++++++++++++++++++++++++ |
117 | Find a particular way. |
118 | |
119 | WayX *FindWayX Returns the extended way with the specified id. |
120 | |
121 | WaysX* waysx The set of ways to process. |
122 | |
123 | way_t id The way id to look for. |
124 | ++++++++++++++++++++++++++++++++++++++*/ |
125 | |
126 | WayX *FindWayX(WaysX* waysx,way_t id) |
127 | { |
128 | int start=0; |
129 | int end=waysx->number-1; |
130 | int mid; |
131 | |
132 | assert(waysx->sorted); /* Must be sorted */ |
133 | assert(waysx->idata); /* Must have idata filled in */ |
134 | |
135 | /* Binary search - search key exact match only is required. |
136 | * |
137 | * # <- start | Check mid and move start or end if it doesn't match |
138 | * # | |
139 | * # | Since an exact match is wanted we can set end=mid-1 |
140 | * # <- mid | or start=mid+1 because we know that mid doesn't match. |
141 | * # | |
142 | * # | Eventually either end=start or end=start+1 and one of |
143 | * # <- end | start or end is the wanted one. |
144 | */ |
145 | |
146 | if(end<start) /* There are no ways */ |
147 | return(NULL); |
148 | else if(id<waysx->idata[start]->id) /* Check key is not before start */ |
149 | return(NULL); |
150 | else if(id>waysx->idata[end]->id) /* Check key is not after end */ |
151 | return(NULL); |
152 | else |
153 | { |
154 | do |
155 | { |
156 | mid=(start+end)/2; /* Choose mid point */ |
157 | |
158 | if(waysx->idata[mid]->id<id) /* Mid point is too low */ |
159 | start=mid+1; |
160 | else if(waysx->idata[mid]->id>id) /* Mid point is too high */ |
161 | end=mid-1; |
162 | else /* Mid point is correct */ |
163 | return(waysx->idata[mid]); |
164 | } |
165 | while((end-start)>1); |
166 | |
167 | if(waysx->idata[start]->id==id) /* Start is correct */ |
168 | return(waysx->idata[start]); |
169 | |
170 | if(waysx->idata[end]->id==id) /* End is correct */ |
171 | return(waysx->idata[end]); |
172 | } |
173 | |
174 | return(NULL); |
175 | } |
176 | |
177 | |
178 | /*++++++++++++++++++++++++++++++++++++++ |
179 | Append a way to a way list. |
180 | |
181 | Way *AppendWay Returns the newly appended way. |
182 | |
183 | WaysX* waysx The set of ways to process. |
184 | |
185 | way_t id The ID of the way. |
186 | |
187 | const char *name The name or reference of the way. |
188 | ++++++++++++++++++++++++++++++++++++++*/ |
189 | |
190 | Way *AppendWay(WaysX* waysx,way_t id,const char *name) |
191 | { |
192 | /* Check that the arrays have enough space. */ |
193 | |
194 | if(waysx->number==waysx->alloced) |
195 | { |
196 | waysx->alloced+=INCREMENT_WAYS; |
197 | |
198 | waysx->xdata=(WayX*)realloc((void*)waysx->xdata,waysx->alloced*sizeof(WayX)); |
199 | |
200 | waysx->wdata=(Way*)realloc((void*)waysx->wdata,waysx->alloced*sizeof(Way)); |
201 | } |
202 | |
203 | /* Insert the way */ |
204 | |
205 | waysx->xdata[waysx->number].id=id; |
206 | waysx->xdata[waysx->number].name=strcpy((char*)malloc(strlen(name)+1),name); |
207 | waysx->xdata[waysx->number].way=&waysx->wdata[waysx->number]; |
208 | |
209 | memset(&waysx->wdata[waysx->number],0,sizeof(Way)); |
210 | |
211 | waysx->number++; |
212 | |
213 | return(&waysx->wdata[waysx->number-1]); |
214 | |
215 | waysx->sorted=0; |
216 | } |
217 | |
218 | |
219 | /*++++++++++++++++++++++++++++++++++++++ |
220 | Sort the list of ways and fix the names. |
221 | |
222 | WaysX* waysx The set of ways to process. |
223 | ++++++++++++++++++++++++++++++++++++++*/ |
224 | |
225 | void SortWayList(WaysX* waysx) |
226 | { |
227 | Way *uniq_ways; |
228 | int i,j; |
229 | |
230 | assert(waysx->xdata); /* Must have xdata filled in */ |
231 | |
232 | printf("Sorting Ways"); fflush(stdout); |
233 | |
234 | /* Sort the ways by id */ |
235 | |
236 | waysx->idata=malloc(waysx->number*sizeof(WayX*)); |
237 | |
238 | for(i=0;i<waysx->number;i++) |
239 | waysx->idata[i]=&waysx->xdata[i]; |
240 | |
241 | qsort(waysx->idata,waysx->number,sizeof(WayX*),(int (*)(const void*,const void*))sort_by_id); |
242 | |
243 | /* Sort the ways by name and way properties */ |
244 | |
245 | waysx->ndata=malloc(waysx->number*sizeof(WayX*)); |
246 | |
247 | for(i=0;i<waysx->number;i++) |
248 | waysx->ndata[i]=&waysx->xdata[i]; |
249 | |
250 | qsort(waysx->ndata,waysx->number,sizeof(WayX*),(int (*)(const void*,const void*))sort_by_name_and_properties); |
251 | |
252 | /* Allocate the new data for names */ |
253 | |
254 | waysx->names=(char*)malloc(waysx->alloced*sizeof(char)); |
255 | |
256 | /* Allocate the data for unique ways */ |
257 | |
258 | uniq_ways=(Way*)malloc(waysx->number*sizeof(Way)); |
259 | |
260 | /* Setup the offsets for the names in the way array */ |
261 | |
262 | for(i=0,j=0;i<waysx->number;i++) |
263 | { |
264 | if(i && !strcmp(waysx->ndata[i]->name,waysx->ndata[i-1]->name)) /* Same name */ |
265 | { |
266 | waysx->ndata[i]->way->name=waysx->ndata[i-1]->way->name; |
267 | |
268 | if(!WaysCompare(waysx->ndata[i]->way,waysx->ndata[i-1]->way)) /* Same properties */ |
269 | waysx->ndata[i]->way=waysx->ndata[i-1]->way; |
270 | else |
271 | { |
272 | uniq_ways[j]=*waysx->ndata[i]->way; |
273 | waysx->ndata[i]->way=&uniq_ways[j++]; |
274 | } |
275 | } |
276 | else /* Different name */ |
277 | { |
278 | if((waysx->length+strlen(waysx->ndata[i]->name)+1)>=waysx->alloced) |
279 | { |
280 | waysx->alloced+=INCREMENT_WAYS; |
281 | |
282 | waysx->names=(char*)realloc((void*)waysx->names,waysx->alloced*sizeof(char)); |
283 | } |
284 | |
285 | strcpy(&waysx->names[waysx->length],waysx->ndata[i]->name); |
286 | |
287 | waysx->ndata[i]->way->name=waysx->length; |
288 | |
289 | waysx->length+=strlen(waysx->ndata[i]->name)+1; |
290 | |
291 | uniq_ways[j]=*waysx->ndata[i]->way; |
292 | waysx->ndata[i]->way=&uniq_ways[j++]; |
293 | } |
294 | } |
295 | |
296 | waysx->wnumber=j; |
297 | |
298 | free(waysx->wdata); |
299 | |
300 | waysx->wdata=uniq_ways; |
301 | |
302 | printf("\rSorted Ways \n"); fflush(stdout); |
303 | |
304 | waysx->sorted=1; |
305 | } |
306 | |
307 | |
308 | /*++++++++++++++++++++++++++++++++++++++ |
309 | Sort the ways into id order. |
310 | |
311 | int sort_by_id Returns the comparison of the id fields. |
312 | |
313 | Way **a The first Way. |
314 | |
315 | Way **b The second Way. |
316 | ++++++++++++++++++++++++++++++++++++++*/ |
317 | |
318 | static int sort_by_id(WayX **a,WayX **b) |
319 | { |
320 | way_t a_id=(*a)->id; |
321 | way_t b_id=(*b)->id; |
322 | |
323 | if(a_id<b_id) |
324 | return(-1); |
325 | else if(a_id>b_id) |
326 | return(1); |
327 | else |
328 | return(0); |
329 | } |
330 | |
331 | |
332 | /*++++++++++++++++++++++++++++++++++++++ |
333 | Sort the ways into name and properties order. |
334 | |
335 | int sort_by_name_and_properties Returns the comparison of the name and properties fields. |
336 | |
337 | Way **a The first Way. |
338 | |
339 | Way **b The second Way. |
340 | ++++++++++++++++++++++++++++++++++++++*/ |
341 | |
342 | static int sort_by_name_and_properties(WayX **a,WayX **b) |
343 | { |
344 | char *a_name=(*a)->name; |
345 | char *b_name=(*b)->name; |
346 | int name_compare; |
347 | |
348 | name_compare=strcmp(a_name,b_name); |
349 | |
350 | if(name_compare) |
351 | return(name_compare); |
352 | else |
353 | { |
354 | Way *a_way=(*a)->way; |
355 | Way *b_way=(*b)->way; |
356 | |
357 | return(WaysCompare(a_way,b_way)); |
358 | } |
359 | } |
Properties
Name | Value |
---|---|
cvs:description | Extended ways functions. |