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 2189 - (show annotations) (download) (as text)
Sun Sep 1 15:38:16 2024 UTC (6 months, 1 week ago) by amb
File MIME type: text/x-csrc
File size: 22301 byte(s)
Change some types and correct some comparisons that cause errors if
index_t is changed to a 64-bit type (prompted by patch from a user).

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

Properties

Name Value
cvs:description Extended ways functions.