Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/waysx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1695 - (show annotations) (download) (as text)
Fri May 29 16:49:00 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 21610 byte(s)
Ensure that allocated strings are long enough even if the %p format is
extravagant in the number of characters it uses.

1 /***************************************
2 Extended Way data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2015 Andrew M. Bishop
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero 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 This program 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 Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ***************************************/
21
22
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "types.h"
27 #include "ways.h"
28
29 #include "typesx.h"
30 #include "nodesx.h"
31 #include "segmentsx.h"
32 #include "waysx.h"
33
34 #include "files.h"
35 #include "logging.h"
36 #include "sorting.h"
37
38
39 /* Global variables */
40
41 /*+ The command line '--tmpdir' option or its default value. +*/
42 extern char *option_tmpdirname;
43
44 /* Local variables */
45
46 /*+ Temporary file-local variables for use by the sort functions. +*/
47 static WaysX *sortwaysx;
48 static SegmentsX *sortsegmentsx;
49
50 /* Local functions */
51
52 static int sort_by_id(WayX *a,WayX *b);
53 static int deduplicate_and_index_by_id(WayX *wayx,index_t index);
54
55 static int sort_by_name(char *a,char *b);
56
57 static int delete_unused(WayX *wayx,index_t index);
58 static int sort_by_name_and_prop_and_id(WayX *a,WayX *b);
59 static int deduplicate_and_index_by_compact_id(WayX *wayx,index_t index);
60
61
62 /*++++++++++++++++++++++++++++++++++++++
63 Allocate a new way list (create a new file or open an existing one).
64
65 WaysX *NewWayList Returns the way list.
66
67 int append Set to 1 if the file is to be opened for appending.
68
69 int readonly Set to 1 if the file is to be opened for reading.
70 ++++++++++++++++++++++++++++++++++++++*/
71
72 WaysX *NewWayList(int append,int readonly)
73 {
74 WaysX *waysx;
75
76 waysx=(WaysX*)calloc(1,sizeof(WaysX));
77
78 logassert(waysx,"Failed to allocate memory (try using slim mode?)"); /* Check calloc() worked */
79
80 waysx->filename =(char*)malloc(strlen(option_tmpdirname)+32);
81 waysx->filename_tmp=(char*)malloc(strlen(option_tmpdirname)+32); /* allow %p to be up to 20 bytes */
82
83 sprintf(waysx->filename ,"%s/waysx.parsed.mem",option_tmpdirname);
84 sprintf(waysx->filename_tmp,"%s/waysx.%p.tmp" ,option_tmpdirname,(void*)waysx);
85
86 if(append || readonly)
87 if(ExistsFile(waysx->filename))
88 {
89 FILESORT_VARINT waysize;
90 int fd;
91
92 fd=ReOpenFileBuffered(waysx->filename);
93
94 while(!ReadFileBuffered(fd,&waysize,FILESORT_VARSIZE))
95 {
96 SkipFileBuffered(fd,waysize);
97
98 waysx->number++;
99 }
100
101 CloseFileBuffered(fd);
102
103 RenameFile(waysx->filename,waysx->filename_tmp);
104 }
105
106 if(append)
107 waysx->fd=OpenFileBufferedAppend(waysx->filename_tmp);
108 else if(!readonly)
109 waysx->fd=OpenFileBufferedNew(waysx->filename_tmp);
110 else
111 waysx->fd=-1;
112
113 #if SLIM
114 waysx->cache=NewWayXCache();
115 log_malloc(waysx->cache,sizeof(*waysx->cache));
116 #endif
117
118
119 waysx->nfilename_tmp=(char*)malloc(strlen(option_tmpdirname)+40); /* allow %p to be up to 20 bytes */
120
121 sprintf(waysx->nfilename_tmp,"%s/waynames.%p.tmp",option_tmpdirname,(void*)waysx);
122
123 return(waysx);
124 }
125
126
127 /*++++++++++++++++++++++++++++++++++++++
128 Free a way list.
129
130 WaysX *waysx The set of ways to be freed.
131
132 int keep If set then the results file is to be kept.
133 ++++++++++++++++++++++++++++++++++++++*/
134
135 void FreeWayList(WaysX *waysx,int keep)
136 {
137 if(keep)
138 RenameFile(waysx->filename_tmp,waysx->filename);
139 else
140 DeleteFile(waysx->filename_tmp);
141
142 free(waysx->filename);
143 free(waysx->filename_tmp);
144
145 if(waysx->idata)
146 {
147 log_free(waysx->idata);
148 free(waysx->idata);
149 }
150
151 if(waysx->odata)
152 {
153 log_free(waysx->odata);
154 free(waysx->odata);
155 }
156
157 if(waysx->cdata)
158 {
159 log_free(waysx->cdata);
160 free(waysx->cdata);
161 }
162
163 DeleteFile(waysx->nfilename_tmp);
164
165 free(waysx->nfilename_tmp);
166
167 #if SLIM
168 log_free(waysx->cache);
169 DeleteWayXCache(waysx->cache);
170 #endif
171
172 free(waysx);
173 }
174
175
176 /*++++++++++++++++++++++++++++++++++++++
177 Append a single way to an unsorted way list.
178
179 WaysX *waysx The set of ways to process.
180
181 way_t id The ID of the way.
182
183 Way *way The way data itself.
184
185 node_t *nodes The list of nodes for this way.
186
187 int nnodes The number of nodes for this way.
188
189 const char *name The name or reference of the way.
190 ++++++++++++++++++++++++++++++++++++++*/
191
192 void AppendWayList(WaysX *waysx,way_t id,Way *way,node_t *nodes,int nnodes,const char *name)
193 {
194 WayX wayx;
195 FILESORT_VARINT size;
196 node_t nonode=NO_NODE_ID;
197
198 wayx.id=id;
199 wayx.way=*way;
200
201 size=sizeof(WayX)+(nnodes+1)*sizeof(node_t)+strlen(name)+1;
202
203 WriteFileBuffered(waysx->fd,&size,FILESORT_VARSIZE);
204 WriteFileBuffered(waysx->fd,&wayx,sizeof(WayX));
205
206 WriteFileBuffered(waysx->fd,nodes ,nnodes*sizeof(node_t));
207 WriteFileBuffered(waysx->fd,&nonode, sizeof(node_t));
208
209 WriteFileBuffered(waysx->fd,name,strlen(name)+1);
210
211 waysx->number++;
212
213 logassert(waysx->number!=0,"Too many ways (change index_t to 64-bits?)"); /* Zero marks the high-water mark for ways. */
214 }
215
216
217 /*++++++++++++++++++++++++++++++++++++++
218 Finish appending ways and change the filename over.
219
220 WaysX *waysx The ways that have been appended.
221 ++++++++++++++++++++++++++++++++++++++*/
222
223 void FinishWayList(WaysX *waysx)
224 {
225 if(waysx->fd!=-1)
226 waysx->fd=CloseFileBuffered(waysx->fd);
227 }
228
229
230 /*++++++++++++++++++++++++++++++++++++++
231 Find a particular way index.
232
233 index_t IndexWayX Returns the index of the extended way with the specified id.
234
235 WaysX *waysx The set of ways to process.
236
237 way_t id The way id to look for.
238 ++++++++++++++++++++++++++++++++++++++*/
239
240 index_t IndexWayX(WaysX *waysx,way_t id)
241 {
242 index_t start=0;
243 index_t end=waysx->number-1;
244 index_t mid;
245
246 if(waysx->number==0) /* There are no ways */
247 return(NO_WAY);
248
249 if(id<waysx->idata[start]) /* Key is before start */
250 return(NO_WAY);
251
252 if(id>waysx->idata[end]) /* Key is after end */
253 return(NO_WAY);
254
255 /* Binary search - search key exact match only is required.
256 *
257 * # <- start | Check mid and move start or end if it doesn't match
258 * # |
259 * # | Since an exact match is wanted we can set end=mid-1
260 * # <- mid | or start=mid+1 because we know that mid doesn't match.
261 * # |
262 * # | Eventually either end=start or end=start+1 and one of
263 * # <- end | start or end is the wanted one.
264 */
265
266 do
267 {
268 mid=(start+end)/2; /* Choose mid point */
269
270 if(waysx->idata[mid]<id) /* Mid point is too low */
271 start=mid+1;
272 else if(waysx->idata[mid]>id) /* Mid point is too high */
273 end=mid?(mid-1):mid;
274 else /* Mid point is correct */
275 return(mid);
276 }
277 while((end-start)>1);
278
279 if(waysx->idata[start]==id) /* Start is correct */
280 return(start);
281
282 if(waysx->idata[end]==id) /* End is correct */
283 return(end);
284
285 return(NO_WAY);
286 }
287
288
289 /*++++++++++++++++++++++++++++++++++++++
290 Sort the list of ways.
291
292 WaysX *waysx The set of ways to process.
293 ++++++++++++++++++++++++++++++++++++++*/
294
295 void SortWayList(WaysX *waysx)
296 {
297 index_t xnumber;
298 int fd;
299
300 /* Print the start message */
301
302 printf_first("Sorting Ways");
303
304 /* Re-open the file read-only and a new file writeable */
305
306 waysx->fd=ReOpenFileBuffered(waysx->filename_tmp);
307
308 DeleteFile(waysx->filename_tmp);
309
310 fd=OpenFileBufferedNew(waysx->filename_tmp);
311
312 /* Allocate the array of indexes */
313
314 waysx->idata=(way_t*)malloc(waysx->number*sizeof(way_t));
315 log_malloc(waysx->idata,waysx->number*sizeof(way_t));
316
317 logassert(waysx->idata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
318
319 /* Sort the ways by ID and index them */
320
321 sortwaysx=waysx;
322
323 xnumber=waysx->number;
324
325 waysx->number=filesort_vary(waysx->fd,fd,NULL,
326 (int (*)(const void*,const void*))sort_by_id,
327 (int (*)(void*,index_t))deduplicate_and_index_by_id);
328
329 waysx->knumber=waysx->number;
330
331 /* Close the files */
332
333 waysx->fd=CloseFileBuffered(waysx->fd);
334 CloseFileBuffered(fd);
335
336 /* Print the final message */
337
338 printf_last("Sorted Ways: Ways=%"Pindex_t" Duplicates=%"Pindex_t,xnumber,xnumber-waysx->number);
339 }
340
341
342 /*++++++++++++++++++++++++++++++++++++++
343 Sort the ways into id order.
344
345 int sort_by_id Returns the comparison of the id fields.
346
347 WayX *a The first extended way.
348
349 WayX *b The second extended way.
350 ++++++++++++++++++++++++++++++++++++++*/
351
352 static int sort_by_id(WayX *a,WayX *b)
353 {
354 way_t a_id=a->id;
355 way_t b_id=b->id;
356
357 if(a_id<b_id)
358 return(-1);
359 else if(a_id>b_id)
360 return(1);
361 else
362 return(-FILESORT_PRESERVE_ORDER(a,b)); /* latest version first */
363 }
364
365
366 /*++++++++++++++++++++++++++++++++++++++
367 Discard duplicate ways and create and index of ids.
368
369 int deduplicate_and_index_by_id Return 1 if the value is to be kept, otherwise 0.
370
371 WayX *wayx The extended way.
372
373 index_t index The number of sorted ways that have already been written to the output file.
374 ++++++++++++++++++++++++++++++++++++++*/
375
376 static int deduplicate_and_index_by_id(WayX *wayx,index_t index)
377 {
378 static way_t previd=NO_WAY_ID;
379
380 if(wayx->id!=previd)
381 {
382 previd=wayx->id;
383
384 if(wayx->way.type==WAY_DELETED)
385 return(0);
386 else
387 {
388 sortwaysx->idata[index]=wayx->id;
389
390 return(1);
391 }
392 }
393 else
394 return(0);
395 }
396
397
398 /*++++++++++++++++++++++++++++++++++++++
399 Split the ways into segments and way names.
400
401 SegmentsX *SplitWays Returns the set of segments that have been created.
402
403 WaysX *waysx The set of ways to process.
404
405 NodesX *nodesx The set of nodes to use.
406
407 int keep If set to 1 then keep the old data file otherwise delete it.
408 ++++++++++++++++++++++++++++++++++++++*/
409
410 SegmentsX *SplitWays(WaysX *waysx,NodesX *nodesx,int keep)
411 {
412 SegmentsX *segmentsx;
413 index_t i;
414 int fd,nfd;
415 char *name=NULL;
416 int namelen=0;
417
418 /* Print the start message */
419
420 printf_first("Splitting Ways: Ways=0 Segments=0");
421
422 segmentsx=NewSegmentList();
423
424 /* Re-open the file read-only and a new file writeable */
425
426 waysx->fd=ReOpenFileBuffered(waysx->filename_tmp);
427
428 if(keep)
429 RenameFile(waysx->filename_tmp,waysx->filename);
430 else
431 DeleteFile(waysx->filename_tmp);
432
433 fd=OpenFileBufferedNew(waysx->filename_tmp);
434
435 nfd=OpenFileBufferedNew(waysx->nfilename_tmp);
436
437 /* Loop through the ways and create the segments and way names */
438
439 for(i=0;i<waysx->number;i++)
440 {
441 WayX wayx;
442 FILESORT_VARINT size;
443 node_t node,prevnode=NO_NODE_ID;
444 index_t index,previndex=NO_NODE;
445
446 ReadFileBuffered(waysx->fd,&size,FILESORT_VARSIZE);
447
448 ReadFileBuffered(waysx->fd,&wayx,sizeof(WayX));
449
450 waysx->allow|=wayx.way.allow;
451
452 while(!ReadFileBuffered(waysx->fd,&node,sizeof(node_t)) && node!=NO_NODE_ID)
453 {
454 index=IndexNodeX(nodesx,node);
455
456 if(prevnode==node)
457 {
458 logerror("Way %"Pway_t" contains node %"Pnode_t" that is connected to itself.\n",logerror_way(waysx->idata[i]),logerror_node(node));
459 }
460 else if(index==NO_NODE)
461 {
462 logerror("Way %"Pway_t" contains node %"Pnode_t" that does not exist in the Routino database.\n",logerror_way(waysx->idata[i]),logerror_node(node));
463 }
464 else if(previndex==NO_NODE)
465 ;
466 else
467 {
468 distance_t segment_flags=0;
469
470 if(wayx.way.type&Highway_OneWay)
471 segment_flags|=ONEWAY_1TO2;
472
473 if(wayx.way.type&Highway_Area)
474 segment_flags|=SEGMENT_AREA;
475
476 AppendSegmentList(segmentsx,i,previndex,index,segment_flags);
477 }
478
479 prevnode=node;
480 previndex=index;
481
482 size-=sizeof(node_t);
483 }
484
485 size-=sizeof(node_t)+sizeof(WayX);
486
487 if(namelen<size)
488 name=(char*)realloc((void*)name,namelen=size);
489
490 ReadFileBuffered(waysx->fd,name,size);
491
492 WriteFileBuffered(fd,&wayx,sizeof(WayX));
493
494 size+=sizeof(index_t);
495
496 WriteFileBuffered(nfd,&size,FILESORT_VARSIZE);
497 WriteFileBuffered(nfd,&i,sizeof(index_t));
498 WriteFileBuffered(nfd,name,size-sizeof(index_t));
499
500 if(!((i+1)%1000))
501 printf_middle("Splitting Ways: Ways=%"Pindex_t" Segments=%"Pindex_t,i+1,segmentsx->number);
502 }
503
504 FinishSegmentList(segmentsx);
505
506 if(name) free(name);
507
508 /* Close the files */
509
510 waysx->fd=CloseFileBuffered(waysx->fd);
511 CloseFileBuffered(fd);
512
513 CloseFileBuffered(nfd);
514
515 /* Print the final message */
516
517 printf_last("Split Ways: Ways=%"Pindex_t" Segments=%"Pindex_t,waysx->number,segmentsx->number);
518
519 return(segmentsx);
520 }
521
522
523
524 /*++++++++++++++++++++++++++++++++++++++
525 Sort the way names and assign the offsets to the ways.
526
527 WaysX *waysx The set of ways to process.
528 ++++++++++++++++++++++++++++++++++++++*/
529
530 void SortWayNames(WaysX *waysx)
531 {
532 index_t i;
533 int nfd;
534 char *names[2]={NULL,NULL};
535 int namelen[2]={0,0};
536 int nnames=0;
537 uint32_t lastlength=0;
538
539 /* Print the start message */
540
541 printf_first("Sorting Way Names");
542
543 /* Re-open the file read-only and new file writeable */
544
545 waysx->nfd=ReOpenFileBuffered(waysx->nfilename_tmp);
546
547 DeleteFile(waysx->nfilename_tmp);
548
549 nfd=OpenFileBufferedNew(waysx->nfilename_tmp);
550
551 /* Sort the way names */
552
553 waysx->nlength=0;
554
555 filesort_vary(waysx->nfd,nfd,NULL,
556 (int (*)(const void*,const void*))sort_by_name,
557 NULL);
558
559 /* Close the files */
560
561 waysx->nfd=CloseFileBuffered(waysx->nfd);
562 CloseFileBuffered(nfd);
563
564 /* Print the final message */
565
566 printf_last("Sorted Way Names: Ways=%"Pindex_t,waysx->number);
567
568
569 /* Print the start message */
570
571 printf_first("Updating Ways with Names: Ways=0 Names=0");
572
573 /* Map into memory / open the file */
574
575 #if !SLIM
576 waysx->data=MapFileWriteable(waysx->filename_tmp);
577 #else
578 waysx->fd=SlimMapFileWriteable(waysx->filename_tmp);
579 #endif
580
581 /* Re-open the file read-only and new file writeable */
582
583 waysx->nfd=ReOpenFileBuffered(waysx->nfilename_tmp);
584
585 DeleteFile(waysx->nfilename_tmp);
586
587 nfd=OpenFileBufferedNew(waysx->nfilename_tmp);
588
589 /* Update the ways and de-duplicate the names */
590
591 for(i=0;i<waysx->number;i++)
592 {
593 WayX *wayx;
594 index_t index;
595 FILESORT_VARINT size;
596
597 ReadFileBuffered(waysx->nfd,&size,FILESORT_VARSIZE);
598
599 if(namelen[nnames%2]<size)
600 names[nnames%2]=(char*)realloc((void*)names[nnames%2],namelen[nnames%2]=size);
601
602 ReadFileBuffered(waysx->nfd,&index,sizeof(index_t));
603 ReadFileBuffered(waysx->nfd,names[nnames%2],size-sizeof(index_t));
604
605 if(nnames==0 || strcmp(names[0],names[1]))
606 {
607 WriteFileBuffered(nfd,names[nnames%2],size-sizeof(index_t));
608
609 lastlength=waysx->nlength;
610 waysx->nlength+=size-sizeof(index_t);
611
612 nnames++;
613 }
614
615 wayx=LookupWayX(waysx,index,1);
616
617 wayx->way.name=lastlength;
618
619 PutBackWayX(waysx,wayx);
620
621 if(!((i+1)%1000))
622 printf_middle("Updating Ways with Names: Ways=%"Pindex_t" Names=%"Pindex_t,i+1,nnames);
623 }
624
625 if(names[0]) free(names[0]);
626 if(names[1]) free(names[1]);
627
628 /* Close the files */
629
630 waysx->nfd=CloseFileBuffered(waysx->nfd);
631 CloseFileBuffered(nfd);
632
633 /* Unmap from memory / close the files */
634
635 #if !SLIM
636 waysx->data=UnmapFile(waysx->data);
637 #else
638 waysx->fd=SlimUnmapFile(waysx->fd);
639 #endif
640
641 /* Print the final message */
642
643 printf_last("Updated Ways with Names: Ways=%"Pindex_t" Names=%"Pindex_t,waysx->number,nnames);
644 }
645
646
647 /*++++++++++++++++++++++++++++++++++++++
648 Sort the ways into name order.
649
650 int sort_by_name Returns the comparison of the name fields.
651
652 char *a The first way name.
653
654 char *b The second way name.
655 ++++++++++++++++++++++++++++++++++++++*/
656
657 static int sort_by_name(char *a,char *b)
658 {
659 int compare;
660 char *a_name=a+sizeof(index_t);
661 char *b_name=b+sizeof(index_t);
662
663 compare=strcmp(a_name,b_name);
664
665 if(compare)
666 return(compare);
667 else
668 return(FILESORT_PRESERVE_ORDER(a,b));
669 }
670
671
672 /*++++++++++++++++++++++++++++++++++++++
673 Compact the way list, removing duplicated ways and unused ways.
674
675 WaysX *waysx The set of ways to process.
676
677 SegmentsX *segmentsx The set of segments to check.
678 ++++++++++++++++++++++++++++++++++++++*/
679
680 void CompactWayList(WaysX *waysx,SegmentsX *segmentsx)
681 {
682 int fd;
683 index_t cnumber;
684
685 if(waysx->number==0)
686 return;
687
688 /* Print the start message */
689
690 printf_first("Sorting Ways and Compacting");
691
692 /* Allocate the array of indexes */
693
694 waysx->cdata=(index_t*)malloc(waysx->number*sizeof(index_t));
695 log_malloc(waysx->cdata,waysx->number*sizeof(index_t));
696
697 logassert(waysx->cdata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
698
699 /* Re-open the file read-only and a new file writeable */
700
701 waysx->fd=ReOpenFileBuffered(waysx->filename_tmp);
702
703 DeleteFile(waysx->filename_tmp);
704
705 fd=OpenFileBufferedNew(waysx->filename_tmp);
706
707 /* Sort the ways to allow compacting according to the properties */
708
709 sortwaysx=waysx;
710 sortsegmentsx=segmentsx;
711
712 cnumber=filesort_fixed(waysx->fd,fd,sizeof(WayX),(int (*)(void*,index_t))delete_unused,
713 (int (*)(const void*,const void*))sort_by_name_and_prop_and_id,
714 (int (*)(void*,index_t))deduplicate_and_index_by_compact_id);
715
716 /* Close the files */
717
718 waysx->fd=CloseFileBuffered(waysx->fd);
719 CloseFileBuffered(fd);
720
721 /* Free the data */
722
723 log_free(segmentsx->usedway);
724 free(segmentsx->usedway);
725 segmentsx->usedway=NULL;
726
727 /* Print the final message */
728
729 printf_last("Sorted and Compacted Ways: Ways=%"Pindex_t" Unique=%"Pindex_t,waysx->number,cnumber);
730 waysx->number=cnumber;
731 }
732
733
734 /*++++++++++++++++++++++++++++++++++++++
735 Delete the ways that are no longer being used.
736
737 int delete_unused Return 1 if the value is to be kept, otherwise 0.
738
739 WayX *wayx The extended way.
740
741 index_t index The number of unsorted ways that have been read from the input file.
742 ++++++++++++++++++++++++++++++++++++++*/
743
744 static int delete_unused(WayX *wayx,index_t index)
745 {
746 if(sortsegmentsx && !IsBitSet(sortsegmentsx->usedway,index))
747 {
748 sortwaysx->cdata[index]=NO_WAY;
749
750 return(0);
751 }
752 else
753 {
754 wayx->id=index;
755
756 return(1);
757 }
758 }
759
760
761 /*++++++++++++++++++++++++++++++++++++++
762 Sort the ways into name, properties and id order.
763
764 int sort_by_name_and_prop_and_id Returns the comparison of the name, properties and id fields.
765
766 WayX *a The first extended Way.
767
768 WayX *b The second extended Way.
769 ++++++++++++++++++++++++++++++++++++++*/
770
771 static int sort_by_name_and_prop_and_id(WayX *a,WayX *b)
772 {
773 int compare;
774 index_t a_name=a->way.name;
775 index_t b_name=b->way.name;
776
777 if(a_name<b_name)
778 return(-1);
779 else if(a_name>b_name)
780 return(1);
781
782 compare=WaysCompare(&a->way,&b->way);
783
784 if(compare)
785 return(compare);
786
787 return(sort_by_id(a,b));
788 }
789
790
791 /*++++++++++++++++++++++++++++++++++++++
792 Create the index of compacted Way identifiers and ignore Ways with duplicated properties.
793
794 int deduplicate_and_index_by_compact_id Return 1 if the value is to be kept, otherwise 0.
795
796 WayX *wayx The extended way.
797
798 index_t index The number of sorted ways that have already been written to the output file.
799 ++++++++++++++++++++++++++++++++++++++*/
800
801 static int deduplicate_and_index_by_compact_id(WayX *wayx,index_t index)
802 {
803 static Way lastway;
804
805 if(index==0 || wayx->way.name!=lastway.name || WaysCompare(&lastway,&wayx->way))
806 {
807 lastway=wayx->way;
808
809 sortwaysx->cdata[wayx->id]=index;
810
811 wayx->id=index;
812
813 return(1);
814 }
815 else
816 {
817 sortwaysx->cdata[wayx->id]=index-1;
818
819 return(0);
820 }
821 }
822
823
824 /*++++++++++++++++++++++++++++++++++++++
825 Save the way list to a file.
826
827 WaysX *waysx The set of ways to save.
828
829 const char *filename The name of the file to save.
830 ++++++++++++++++++++++++++++++++++++++*/
831
832 void SaveWayList(WaysX *waysx,const char *filename)
833 {
834 index_t i;
835 int fd;
836 index_t position=0;
837 WayX wayx;
838 WaysFile waysfile={0};
839 highways_t highways=0;
840 transports_t allow=0;
841 properties_t props=0;
842
843 /* Print the start message */
844
845 printf_first("Writing Ways: Ways=0");
846
847 /* Re-open the files */
848
849 waysx->fd=ReOpenFileBuffered(waysx->filename_tmp);
850 waysx->nfd=ReOpenFileBuffered(waysx->nfilename_tmp);
851
852 /* Write out the ways data */
853
854 fd=OpenFileBufferedNew(filename);
855
856 SeekFileBuffered(fd,sizeof(WaysFile));
857
858 for(i=0;i<waysx->number;i++)
859 {
860 ReadFileBuffered(waysx->fd,&wayx,sizeof(WayX));
861
862 highways|=HIGHWAYS(wayx.way.type);
863 allow |=wayx.way.allow;
864 props |=wayx.way.props;
865
866 WriteFileBuffered(fd,&wayx.way,sizeof(Way));
867
868 if(!((i+1)%1000))
869 printf_middle("Writing Ways: Ways=%"Pindex_t,i+1);
870 }
871
872 /* Write out the ways names */
873
874 SeekFileBuffered(fd,sizeof(WaysFile)+(off_t)waysx->number*sizeof(Way));
875
876 while(position<waysx->nlength)
877 {
878 size_t len=1024;
879 char temp[1024];
880
881 if((waysx->nlength-position)<1024)
882 len=waysx->nlength-position;
883
884 ReadFileBuffered(waysx->nfd,temp,len);
885
886 WriteFileBuffered(fd,temp,len);
887
888 position+=len;
889 }
890
891 /* Close the files */
892
893 waysx->fd=CloseFileBuffered(waysx->fd);
894 waysx->nfd=CloseFileBuffered(waysx->nfd);
895
896 /* Write out the header structure */
897
898 waysfile.number =waysx->number;
899
900 waysfile.highways=highways;
901 waysfile.allow =allow;
902 waysfile.props =props;
903
904 SeekFileBuffered(fd,0);
905 WriteFileBuffered(fd,&waysfile,sizeof(WaysFile));
906
907 CloseFileBuffered(fd);
908
909 /* Print the final message */
910
911 printf_last("Wrote Ways: Ways=%"Pindex_t,waysx->number);
912 }

Properties

Name Value
cvs:description Extended ways functions.