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 1991 - (show annotations) (download) (as text)
Wed Apr 17 18:04:53 2019 UTC (5 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 21781 byte(s)
Rename some structure members and function names to reflect more
clearly their meaaning (mostly change "allow" to "transport").  No
changes to file formats or API.

1 /***************************************
2 Extended Way data type functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2015, 2018, 2019 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 (re-initialised for each sort). +*/
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 uint64_t longsize;
196 FILESORT_VARINT size;
197 node_t nonode=NO_NODE_ID;
198
199 wayx.id=id;
200 wayx.way=*way;
201
202 longsize=sizeof(WayX)+(nnodes+1)*sizeof(node_t)+strlen(name)+1;
203
204 logassert(longsize<FILESORT_MAXINT,"Way contains too much data (change FILESORT_VARINT to 32-bits?)"); /* Ensure no overflow of FILESORT_VARINT integer */
205
206 size=longsize;
207
208 WriteFileBuffered(waysx->fd,&size,FILESORT_VARSIZE);
209 WriteFileBuffered(waysx->fd,&wayx,sizeof(WayX));
210
211 WriteFileBuffered(waysx->fd,nodes ,nnodes*sizeof(node_t));
212 WriteFileBuffered(waysx->fd,&nonode, sizeof(node_t));
213
214 WriteFileBuffered(waysx->fd,name,strlen(name)+1);
215
216 waysx->number++;
217
218 logassert(waysx->number!=0,"Too many ways (change index_t to 64-bits?)"); /* Zero marks the high-water mark for ways. */
219 }
220
221
222 /*++++++++++++++++++++++++++++++++++++++
223 Finish appending ways and change the filename over.
224
225 WaysX *waysx The ways that have been appended.
226 ++++++++++++++++++++++++++++++++++++++*/
227
228 void FinishWayList(WaysX *waysx)
229 {
230 if(waysx->fd!=-1)
231 waysx->fd=CloseFileBuffered(waysx->fd);
232 }
233
234
235 /*++++++++++++++++++++++++++++++++++++++
236 Find a particular way index.
237
238 index_t IndexWayX Returns the index of the extended way with the specified id.
239
240 WaysX *waysx The set of ways to process.
241
242 way_t id The way id to look for.
243 ++++++++++++++++++++++++++++++++++++++*/
244
245 index_t IndexWayX(WaysX *waysx,way_t id)
246 {
247 index_t start=0;
248 index_t end=waysx->number-1;
249 index_t mid;
250
251 if(waysx->number==0) /* There are no ways */
252 return(NO_WAY);
253
254 if(id<waysx->idata[start]) /* Key is before start */
255 return(NO_WAY);
256
257 if(id>waysx->idata[end]) /* Key is after end */
258 return(NO_WAY);
259
260 /* Binary search - search key exact match only is required.
261 *
262 * # <- start | Check mid and move start or end if it doesn't match
263 * # |
264 * # | Since an exact match is wanted we can set end=mid-1
265 * # <- mid | or start=mid+1 because we know that mid doesn't match.
266 * # |
267 * # | Eventually either end=start or end=start+1 and one of
268 * # <- end | start or end is the wanted one.
269 */
270
271 do
272 {
273 mid=start+(end-start)/2; /* Choose mid point (avoid overflow) */
274
275 if(waysx->idata[mid]<id) /* Mid point is too low */
276 start=mid+1;
277 else if(waysx->idata[mid]>id) /* Mid point is too high */
278 end=mid?(mid-1):mid;
279 else /* Mid point is correct */
280 return(mid);
281 }
282 while((end-start)>1);
283
284 if(waysx->idata[start]==id) /* Start is correct */
285 return(start);
286
287 if(waysx->idata[end]==id) /* End is correct */
288 return(end);
289
290 return(NO_WAY);
291 }
292
293
294 /*++++++++++++++++++++++++++++++++++++++
295 Sort the list of ways.
296
297 WaysX *waysx The set of ways to process.
298 ++++++++++++++++++++++++++++++++++++++*/
299
300 void SortWayList(WaysX *waysx)
301 {
302 index_t xnumber;
303 int fd;
304
305 /* Print the start message */
306
307 printf_first("Sorting Ways");
308
309 /* Re-open the file read-only and a new file writeable */
310
311 fd=ReplaceFileBuffered(waysx->filename_tmp,&waysx->fd);
312
313 /* Allocate the array of indexes */
314
315 waysx->idata=(way_t*)malloc(waysx->number*sizeof(way_t));
316 log_malloc(waysx->idata,waysx->number*sizeof(way_t));
317
318 logassert(waysx->idata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
319
320 /* Sort the ways by ID and index them */
321
322 sortwaysx=waysx;
323
324 xnumber=waysx->number;
325
326 waysx->number=filesort_vary(waysx->fd,fd,NULL,
327 (int (*)(const void*,const void*))sort_by_id,
328 (int (*)(void*,index_t))deduplicate_and_index_by_id);
329
330 waysx->knumber=waysx->number;
331
332 /* Close the files */
333
334 waysx->fd=CloseFileBuffered(waysx->fd);
335 CloseFileBuffered(fd);
336
337 /* Print the final message */
338
339 printf_last("Sorted Ways: Ways=%"Pindex_t" Duplicates=%"Pindex_t,xnumber,xnumber-waysx->number);
340 }
341
342
343 /*++++++++++++++++++++++++++++++++++++++
344 Sort the ways into id order.
345
346 int sort_by_id Returns the comparison of the id fields.
347
348 WayX *a The first extended way.
349
350 WayX *b The second extended way.
351 ++++++++++++++++++++++++++++++++++++++*/
352
353 static int sort_by_id(WayX *a,WayX *b)
354 {
355 way_t a_id=a->id;
356 way_t b_id=b->id;
357
358 if(a_id<b_id)
359 return(-1);
360 else if(a_id>b_id)
361 return(1);
362 else
363 return(-FILESORT_PRESERVE_ORDER(a,b)); /* latest version first */
364 }
365
366
367 /*++++++++++++++++++++++++++++++++++++++
368 Discard duplicate ways and create and index of ids.
369
370 int deduplicate_and_index_by_id Return 1 if the value is to be kept, otherwise 0.
371
372 WayX *wayx The extended way.
373
374 index_t index The number of sorted ways that have already been written to the output file.
375 ++++++++++++++++++++++++++++++++++++++*/
376
377 static int deduplicate_and_index_by_id(WayX *wayx,index_t index)
378 {
379 static way_t previd; /* internal variable (reset by first call in each sort; index==0) */
380
381 if(index==0 || wayx->id!=previd)
382 {
383 previd=wayx->id;
384
385 if(wayx->way.type==WAY_DELETED)
386 return(0);
387 else
388 {
389 sortwaysx->idata[index]=wayx->id;
390
391 return(1);
392 }
393 }
394 else
395 return(0);
396 }
397
398
399 /*++++++++++++++++++++++++++++++++++++++
400 Split the ways into segments and way names.
401
402 SegmentsX *SplitWays Returns the set of segments that have been created.
403
404 WaysX *waysx The set of ways to process.
405
406 NodesX *nodesx The set of nodes to use.
407
408 int keep If set to 1 then keep the old data file otherwise delete it.
409 ++++++++++++++++++++++++++++++++++++++*/
410
411 SegmentsX *SplitWays(WaysX *waysx,NodesX *nodesx,int keep)
412 {
413 SegmentsX *segmentsx;
414 index_t i;
415 int fd,nfd;
416 char *name=NULL;
417 uint32_t namelen=0;
418
419 /* Print the start message */
420
421 printf_first("Splitting Ways: Ways=0 Segments=0");
422
423 segmentsx=NewSegmentList();
424
425 /* Re-open the file read-only and a new file writeable */
426
427 if(keep)
428 {
429 RenameFile(waysx->filename_tmp,waysx->filename);
430
431 waysx->fd=ReOpenFileBuffered(waysx->filename);
432
433 fd=OpenFileBufferedNew(waysx->filename_tmp);
434 }
435 else
436 fd=ReplaceFileBuffered(waysx->filename_tmp,&waysx->fd);
437
438 nfd=OpenFileBufferedNew(waysx->nfilename_tmp);
439
440 /* Loop through the ways and create the segments and way names */
441
442 for(i=0;i<waysx->number;i++)
443 {
444 WayX wayx;
445 FILESORT_VARINT size;
446 node_t node,prevnode=NO_NODE_ID;
447 index_t index,previndex=NO_NODE;
448
449 ReadFileBuffered(waysx->fd,&size,FILESORT_VARSIZE);
450
451 ReadFileBuffered(waysx->fd,&wayx,sizeof(WayX));
452
453 waysx->transports|=wayx.way.allow;
454
455 while(!ReadFileBuffered(waysx->fd,&node,sizeof(node_t)) && node!=NO_NODE_ID)
456 {
457 index=IndexNodeX(nodesx,node);
458
459 if(prevnode==node)
460 {
461 logerror("Way %"Pway_t" contains node %"Pnode_t" that is connected to itself.\n",logerror_way(waysx->idata[i]),logerror_node(node));
462 }
463 else if(index==NO_NODE)
464 {
465 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));
466 }
467 else if(previndex==NO_NODE)
468 ;
469 else
470 {
471 distance_t segment_flags=0;
472
473 if(wayx.way.type&Highway_OneWay)
474 segment_flags|=ONEWAY_1TO2;
475
476 if(wayx.way.type&Highway_Area)
477 segment_flags|=SEGMENT_AREA;
478
479 AppendSegmentList(segmentsx,i,previndex,index,segment_flags);
480 }
481
482 prevnode=node;
483 previndex=index;
484
485 size-=sizeof(node_t);
486 }
487
488 size-=sizeof(node_t)+sizeof(WayX);
489
490 if(namelen<size)
491 name=(char*)realloc((void*)name,namelen=size);
492
493 ReadFileBuffered(waysx->fd,name,size);
494
495 WriteFileBuffered(fd,&wayx,sizeof(WayX));
496
497 size+=sizeof(index_t);
498
499 WriteFileBuffered(nfd,&size,FILESORT_VARSIZE);
500 WriteFileBuffered(nfd,&i,sizeof(index_t));
501 WriteFileBuffered(nfd,name,size-sizeof(index_t));
502
503 if(!((i+1)%1000))
504 printf_middle("Splitting Ways: Ways=%"Pindex_t" Segments=%"Pindex_t,i+1,segmentsx->number);
505 }
506
507 FinishSegmentList(segmentsx);
508
509 if(name) free(name);
510
511 /* Close the files */
512
513 waysx->fd=CloseFileBuffered(waysx->fd);
514 CloseFileBuffered(fd);
515
516 CloseFileBuffered(nfd);
517
518 /* Print the final message */
519
520 printf_last("Split Ways: Ways=%"Pindex_t" Segments=%"Pindex_t,waysx->number,segmentsx->number);
521
522 return(segmentsx);
523 }
524
525
526
527 /*++++++++++++++++++++++++++++++++++++++
528 Sort the way names and assign the offsets to the ways.
529
530 WaysX *waysx The set of ways to process.
531 ++++++++++++++++++++++++++++++++++++++*/
532
533 void SortWayNames(WaysX *waysx)
534 {
535 index_t i;
536 int nfd;
537 char *names[2]={NULL,NULL};
538 uint32_t namelen[2]={0,0};
539 int nnames=0;
540 uint32_t lastlength=0;
541
542 /* Print the start message */
543
544 printf_first("Sorting Way Names");
545
546 /* Re-open the file read-only and new file writeable */
547
548 nfd=ReplaceFileBuffered(waysx->nfilename_tmp,&waysx->nfd);
549
550 /* Sort the way names */
551
552 waysx->nlength=0;
553
554 filesort_vary(waysx->nfd,nfd,NULL,
555 (int (*)(const void*,const void*))sort_by_name,
556 NULL);
557
558 /* Close the files */
559
560 waysx->nfd=CloseFileBuffered(waysx->nfd);
561 CloseFileBuffered(nfd);
562
563 /* Print the final message */
564
565 printf_last("Sorted Way Names: Ways=%"Pindex_t,waysx->number);
566
567
568 /* Print the start message */
569
570 printf_first("Updating Ways with Names: Ways=0 Names=0");
571
572 /* Map into memory / open the file */
573
574 #if !SLIM
575 waysx->data=MapFileWriteable(waysx->filename_tmp);
576 #else
577 waysx->fd=SlimMapFileWriteable(waysx->filename_tmp);
578 #endif
579
580 /* Re-open the file read-only and new file writeable */
581
582 nfd=ReplaceFileBuffered(waysx->nfilename_tmp,&waysx->nfd);
583
584 /* Update the ways and de-duplicate the names */
585
586 for(i=0;i<waysx->number;i++)
587 {
588 WayX *wayx;
589 index_t index;
590 FILESORT_VARINT size;
591
592 ReadFileBuffered(waysx->nfd,&size,FILESORT_VARSIZE);
593
594 if(namelen[nnames%2]<size)
595 names[nnames%2]=(char*)realloc((void*)names[nnames%2],namelen[nnames%2]=size);
596
597 ReadFileBuffered(waysx->nfd,&index,sizeof(index_t));
598 ReadFileBuffered(waysx->nfd,names[nnames%2],size-sizeof(index_t));
599
600 if(nnames==0 || strcmp(names[0],names[1]))
601 {
602 WriteFileBuffered(nfd,names[nnames%2],size-sizeof(index_t));
603
604 lastlength=waysx->nlength;
605 waysx->nlength+=size-sizeof(index_t);
606
607 nnames++;
608 }
609
610 wayx=LookupWayX(waysx,index,1);
611
612 wayx->way.name=lastlength;
613
614 PutBackWayX(waysx,wayx);
615
616 if(!((i+1)%1000))
617 printf_middle("Updating Ways with Names: Ways=%"Pindex_t" Names=%"Pindex_t,i+1,nnames);
618 }
619
620 if(names[0]) free(names[0]);
621 if(names[1]) free(names[1]);
622
623 /* Close the files */
624
625 waysx->nfd=CloseFileBuffered(waysx->nfd);
626 CloseFileBuffered(nfd);
627
628 /* Unmap from memory / close the files */
629
630 #if !SLIM
631 waysx->data=UnmapFile(waysx->data);
632 #else
633 waysx->fd=SlimUnmapFile(waysx->fd);
634 #endif
635
636 /* Print the final message */
637
638 printf_last("Updated Ways with Names: Ways=%"Pindex_t" Names=%"Pindex_t,waysx->number,nnames);
639 }
640
641
642 /*++++++++++++++++++++++++++++++++++++++
643 Sort the ways into name order.
644
645 int sort_by_name Returns the comparison of the name fields.
646
647 char *a The first way name.
648
649 char *b The second way name.
650 ++++++++++++++++++++++++++++++++++++++*/
651
652 static int sort_by_name(char *a,char *b)
653 {
654 int compare;
655 char *a_name=a+sizeof(index_t);
656 char *b_name=b+sizeof(index_t);
657
658 compare=strcmp(a_name,b_name);
659
660 if(compare)
661 return(compare);
662 else
663 return(FILESORT_PRESERVE_ORDER(a,b));
664 }
665
666
667 /*++++++++++++++++++++++++++++++++++++++
668 Compact the way list, removing duplicated ways and unused ways.
669
670 WaysX *waysx The set of ways to process.
671
672 SegmentsX *segmentsx The set of segments to check.
673 ++++++++++++++++++++++++++++++++++++++*/
674
675 void CompactWayList(WaysX *waysx,SegmentsX *segmentsx)
676 {
677 int fd;
678 index_t cnumber;
679
680 if(waysx->number==0)
681 return;
682
683 /* Print the start message */
684
685 printf_first("Sorting Ways and Compacting");
686
687 /* Allocate the array of indexes */
688
689 waysx->cdata=(index_t*)malloc(waysx->number*sizeof(index_t));
690 log_malloc(waysx->cdata,waysx->number*sizeof(index_t));
691
692 logassert(waysx->cdata,"Failed to allocate memory (try using slim mode?)"); /* Check malloc() worked */
693
694 /* Re-open the file read-only and a new file writeable */
695
696 fd=ReplaceFileBuffered(waysx->filename_tmp,&waysx->fd);
697
698 /* Sort the ways to allow compacting according to the properties */
699
700 sortwaysx=waysx;
701 sortsegmentsx=segmentsx;
702
703 cnumber=filesort_fixed(waysx->fd,fd,sizeof(WayX),(int (*)(void*,index_t))delete_unused,
704 (int (*)(const void*,const void*))sort_by_name_and_prop_and_id,
705 (int (*)(void*,index_t))deduplicate_and_index_by_compact_id);
706
707 /* Close the files */
708
709 waysx->fd=CloseFileBuffered(waysx->fd);
710 CloseFileBuffered(fd);
711
712 /* Free the data */
713
714 log_free(segmentsx->usedway);
715 free(segmentsx->usedway);
716 segmentsx->usedway=NULL;
717
718 /* Print the final message */
719
720 printf_last("Sorted and Compacted Ways: Ways=%"Pindex_t" Unique=%"Pindex_t,waysx->number,cnumber);
721 waysx->number=cnumber;
722 }
723
724
725 /*++++++++++++++++++++++++++++++++++++++
726 Delete the ways that are no longer being used.
727
728 int delete_unused Return 1 if the value is to be kept, otherwise 0.
729
730 WayX *wayx The extended way.
731
732 index_t index The number of unsorted ways that have been read from the input file.
733 ++++++++++++++++++++++++++++++++++++++*/
734
735 static int delete_unused(WayX *wayx,index_t index)
736 {
737 if(sortsegmentsx && !IsBitSet(sortsegmentsx->usedway,index))
738 {
739 sortwaysx->cdata[index]=NO_WAY;
740
741 return(0);
742 }
743 else
744 {
745 wayx->id=index;
746
747 return(1);
748 }
749 }
750
751
752 /*++++++++++++++++++++++++++++++++++++++
753 Sort the ways into name, properties and id order.
754
755 int sort_by_name_and_prop_and_id Returns the comparison of the name, properties and id fields.
756
757 WayX *a The first extended Way.
758
759 WayX *b The second extended Way.
760 ++++++++++++++++++++++++++++++++++++++*/
761
762 static int sort_by_name_and_prop_and_id(WayX *a,WayX *b)
763 {
764 int compare;
765 index_t a_name=a->way.name;
766 index_t b_name=b->way.name;
767
768 if(a_name<b_name)
769 return(-1);
770 else if(a_name>b_name)
771 return(1);
772
773 compare=WaysCompare(&a->way,&b->way);
774
775 if(compare)
776 return(compare);
777
778 return(sort_by_id(a,b));
779 }
780
781
782 /*++++++++++++++++++++++++++++++++++++++
783 Create the index of compacted Way identifiers and ignore Ways with duplicated properties.
784
785 int deduplicate_and_index_by_compact_id Return 1 if the value is to be kept, otherwise 0.
786
787 WayX *wayx The extended way.
788
789 index_t index The number of sorted ways that have already been written to the output file.
790 ++++++++++++++++++++++++++++++++++++++*/
791
792 static int deduplicate_and_index_by_compact_id(WayX *wayx,index_t index)
793 {
794 static Way lastway; /* internal variable (reset by first call in each sort; index==0) */
795
796 if(index==0 || wayx->way.name!=lastway.name || WaysCompare(&lastway,&wayx->way))
797 {
798 lastway=wayx->way;
799
800 sortwaysx->cdata[wayx->id]=index;
801
802 wayx->id=index;
803
804 return(1);
805 }
806 else
807 {
808 sortwaysx->cdata[wayx->id]=index-1;
809
810 return(0);
811 }
812 }
813
814
815 /*++++++++++++++++++++++++++++++++++++++
816 Save the way list to a file.
817
818 WaysX *waysx The set of ways to save.
819
820 const char *filename The name of the file to save.
821 ++++++++++++++++++++++++++++++++++++++*/
822
823 void SaveWayList(WaysX *waysx,const char *filename)
824 {
825 index_t i;
826 int fd;
827 index_t position=0;
828 WayX wayx;
829 WaysFile waysfile={0};
830 highways_t highways=0;
831 transports_t transports=0;
832 properties_t properties=0;
833
834 /* Print the start message */
835
836 printf_first("Writing Ways: Ways=0");
837
838 /* Re-open the files */
839
840 waysx->fd=ReOpenFileBuffered(waysx->filename_tmp);
841 waysx->nfd=ReOpenFileBuffered(waysx->nfilename_tmp);
842
843 /* Write out the ways data */
844
845 fd=OpenFileBufferedNew(filename);
846
847 SeekFileBuffered(fd,sizeof(WaysFile));
848
849 for(i=0;i<waysx->number;i++)
850 {
851 ReadFileBuffered(waysx->fd,&wayx,sizeof(WayX));
852
853 highways |=HIGHWAYS(wayx.way.type);
854 transports|=wayx.way.allow;
855 properties|=wayx.way.props;
856
857 WriteFileBuffered(fd,&wayx.way,sizeof(Way));
858
859 if(!((i+1)%1000))
860 printf_middle("Writing Ways: Ways=%"Pindex_t,i+1);
861 }
862
863 /* Write out the ways names */
864
865 SeekFileBuffered(fd,sizeof(WaysFile)+(offset_t)waysx->number*sizeof(Way));
866
867 while(position<waysx->nlength)
868 {
869 size_t len=1024;
870 char temp[1024];
871
872 if((waysx->nlength-position)<1024)
873 len=waysx->nlength-position;
874
875 ReadFileBuffered(waysx->nfd,temp,len);
876
877 WriteFileBuffered(fd,temp,len);
878
879 position+=len;
880 }
881
882 /* Close the files */
883
884 waysx->fd=CloseFileBuffered(waysx->fd);
885 waysx->nfd=CloseFileBuffered(waysx->nfd);
886
887 /* Write out the header structure */
888
889 waysfile.number =waysx->number;
890
891 waysfile.highways =highways;
892 waysfile.transports=transports;
893 waysfile.properties=properties;
894
895 SeekFileBuffered(fd,0);
896 WriteFileBuffered(fd,&waysfile,sizeof(WaysFile));
897
898 CloseFileBuffered(fd);
899
900 /* Print the final message */
901
902 printf_last("Wrote Ways: Ways=%"Pindex_t,waysx->number);
903 }

Properties

Name Value
cvs:description Extended ways functions.