Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /branches/libroutino/src/profiles.c
Parent Directory
|
Revision Log
Revision 1711 -
(show annotations)
(download)
(as text)
Tue Jun 16 19:05:31 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 34467 byte(s)
Tue Jun 16 19:05:31 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 34467 byte(s)
Audit the use of file static variables to make sure that there are no implicit assumptions about initialisation conditions that would be wrong for library usage. Fix problems and add comments for clarity.
1 | /*************************************** |
2 | Load the profiles from a file and the functions for handling them. |
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 <stdio.h> |
24 | #include <string.h> |
25 | #include <stdlib.h> |
26 | #include <math.h> |
27 | |
28 | #include "types.h" |
29 | #include "ways.h" |
30 | |
31 | #include "files.h" |
32 | #include "profiles.h" |
33 | #include "xmlparse.h" |
34 | |
35 | |
36 | /* Local variables (re-intialised by FreeXMLProfiles() function) */ |
37 | |
38 | /*+ The profiles that have been loaded from file. +*/ |
39 | static Profile **loaded_profiles; |
40 | |
41 | /*+ The number of profiles that have been loaded from file. +*/ |
42 | static int nloaded_profiles=0; |
43 | |
44 | |
45 | /* The XML tag processing function prototypes */ |
46 | |
47 | //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding); |
48 | //static int RoutinoProfilesType_function(const char *_tag_,int _type_); |
49 | static int profileType_function(const char *_tag_,int _type_,const char *name,const char *transport); |
50 | //static int speedsType_function(const char *_tag_,int _type_); |
51 | //static int preferencesType_function(const char *_tag_,int _type_); |
52 | //static int propertiesType_function(const char *_tag_,int _type_); |
53 | //static int restrictionsType_function(const char *_tag_,int _type_); |
54 | static int speedType_function(const char *_tag_,int _type_,const char *highway,const char *kph); |
55 | static int preferenceType_function(const char *_tag_,int _type_,const char *highway,const char *percent); |
56 | static int propertyType_function(const char *_tag_,int _type_,const char *type,const char *percent); |
57 | static int onewayType_function(const char *_tag_,int _type_,const char *obey); |
58 | static int turnsType_function(const char *_tag_,int _type_,const char *obey); |
59 | static int weightType_function(const char *_tag_,int _type_,const char *limit); |
60 | static int heightType_function(const char *_tag_,int _type_,const char *limit); |
61 | static int widthType_function(const char *_tag_,int _type_,const char *limit); |
62 | static int lengthType_function(const char *_tag_,int _type_,const char *limit); |
63 | |
64 | |
65 | /* The XML tag definitions (forward declarations) */ |
66 | |
67 | static xmltag xmlDeclaration_tag; |
68 | static xmltag RoutinoProfilesType_tag; |
69 | static xmltag profileType_tag; |
70 | static xmltag speedsType_tag; |
71 | static xmltag preferencesType_tag; |
72 | static xmltag propertiesType_tag; |
73 | static xmltag restrictionsType_tag; |
74 | static xmltag speedType_tag; |
75 | static xmltag preferenceType_tag; |
76 | static xmltag propertyType_tag; |
77 | static xmltag onewayType_tag; |
78 | static xmltag turnsType_tag; |
79 | static xmltag weightType_tag; |
80 | static xmltag heightType_tag; |
81 | static xmltag widthType_tag; |
82 | static xmltag lengthType_tag; |
83 | |
84 | |
85 | /* The XML tag definition values */ |
86 | |
87 | /*+ The complete set of tags at the top level. +*/ |
88 | static xmltag *xml_toplevel_tags[]={&xmlDeclaration_tag,&RoutinoProfilesType_tag,NULL}; |
89 | |
90 | /*+ The xmlDeclaration type tag. +*/ |
91 | static xmltag xmlDeclaration_tag= |
92 | {"xml", |
93 | 2, {"version","encoding"}, |
94 | NULL, |
95 | {NULL}}; |
96 | |
97 | /*+ The RoutinoProfilesType type tag. +*/ |
98 | static xmltag RoutinoProfilesType_tag= |
99 | {"routino-profiles", |
100 | 0, {NULL}, |
101 | NULL, |
102 | {&profileType_tag,NULL}}; |
103 | |
104 | /*+ The profileType type tag. +*/ |
105 | static xmltag profileType_tag= |
106 | {"profile", |
107 | 2, {"name","transport"}, |
108 | profileType_function, |
109 | {&speedsType_tag,&preferencesType_tag,&propertiesType_tag,&restrictionsType_tag,NULL}}; |
110 | |
111 | /*+ The speedsType type tag. +*/ |
112 | static xmltag speedsType_tag= |
113 | {"speeds", |
114 | 0, {NULL}, |
115 | NULL, |
116 | {&speedType_tag,NULL}}; |
117 | |
118 | /*+ The preferencesType type tag. +*/ |
119 | static xmltag preferencesType_tag= |
120 | {"preferences", |
121 | 0, {NULL}, |
122 | NULL, |
123 | {&preferenceType_tag,NULL}}; |
124 | |
125 | /*+ The propertiesType type tag. +*/ |
126 | static xmltag propertiesType_tag= |
127 | {"properties", |
128 | 0, {NULL}, |
129 | NULL, |
130 | {&propertyType_tag,NULL}}; |
131 | |
132 | /*+ The restrictionsType type tag. +*/ |
133 | static xmltag restrictionsType_tag= |
134 | {"restrictions", |
135 | 0, {NULL}, |
136 | NULL, |
137 | {&onewayType_tag,&turnsType_tag,&weightType_tag,&heightType_tag,&widthType_tag,&lengthType_tag,NULL}}; |
138 | |
139 | /*+ The speedType type tag. +*/ |
140 | static xmltag speedType_tag= |
141 | {"speed", |
142 | 2, {"highway","kph"}, |
143 | speedType_function, |
144 | {NULL}}; |
145 | |
146 | /*+ The preferenceType type tag. +*/ |
147 | static xmltag preferenceType_tag= |
148 | {"preference", |
149 | 2, {"highway","percent"}, |
150 | preferenceType_function, |
151 | {NULL}}; |
152 | |
153 | /*+ The propertyType type tag. +*/ |
154 | static xmltag propertyType_tag= |
155 | {"property", |
156 | 2, {"type","percent"}, |
157 | propertyType_function, |
158 | {NULL}}; |
159 | |
160 | /*+ The onewayType type tag. +*/ |
161 | static xmltag onewayType_tag= |
162 | {"oneway", |
163 | 1, {"obey"}, |
164 | onewayType_function, |
165 | {NULL}}; |
166 | |
167 | /*+ The turnsType type tag. +*/ |
168 | static xmltag turnsType_tag= |
169 | {"turns", |
170 | 1, {"obey"}, |
171 | turnsType_function, |
172 | {NULL}}; |
173 | |
174 | /*+ The weightType type tag. +*/ |
175 | static xmltag weightType_tag= |
176 | {"weight", |
177 | 1, {"limit"}, |
178 | weightType_function, |
179 | {NULL}}; |
180 | |
181 | /*+ The heightType type tag. +*/ |
182 | static xmltag heightType_tag= |
183 | {"height", |
184 | 1, {"limit"}, |
185 | heightType_function, |
186 | {NULL}}; |
187 | |
188 | /*+ The widthType type tag. +*/ |
189 | static xmltag widthType_tag= |
190 | {"width", |
191 | 1, {"limit"}, |
192 | widthType_function, |
193 | {NULL}}; |
194 | |
195 | /*+ The lengthType type tag. +*/ |
196 | static xmltag lengthType_tag= |
197 | {"length", |
198 | 1, {"limit"}, |
199 | lengthType_function, |
200 | {NULL}}; |
201 | |
202 | |
203 | /* The XML tag processing functions */ |
204 | |
205 | |
206 | /*++++++++++++++++++++++++++++++++++++++ |
207 | The function that is called when the XML declaration is seen |
208 | |
209 | int xmlDeclaration_function Returns 0 if no error occured or something else otherwise. |
210 | |
211 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
212 | |
213 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
214 | |
215 | const char *version The contents of the 'version' attribute (or NULL if not defined). |
216 | |
217 | const char *encoding The contents of the 'encoding' attribute (or NULL if not defined). |
218 | ++++++++++++++++++++++++++++++++++++++*/ |
219 | |
220 | //static int xmlDeclaration_function(const char *_tag_,int _type_,const char *version,const char *encoding) |
221 | //{ |
222 | // return(0); |
223 | //} |
224 | |
225 | |
226 | /*++++++++++++++++++++++++++++++++++++++ |
227 | The function that is called when the RoutinoProfilesType XSD type is seen |
228 | |
229 | int RoutinoProfilesType_function Returns 0 if no error occured or something else otherwise. |
230 | |
231 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
232 | |
233 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
234 | ++++++++++++++++++++++++++++++++++++++*/ |
235 | |
236 | //static int RoutinoProfilesType_function(const char *_tag_,int _type_) |
237 | //{ |
238 | // return(0); |
239 | //} |
240 | |
241 | |
242 | /*++++++++++++++++++++++++++++++++++++++ |
243 | The function that is called when the profileType XSD type is seen |
244 | |
245 | int profileType_function Returns 0 if no error occured or something else otherwise. |
246 | |
247 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
248 | |
249 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
250 | |
251 | const char *name The contents of the 'name' attribute (or NULL if not defined). |
252 | |
253 | const char *transport The contents of the 'transport' attribute (or NULL if not defined). |
254 | ++++++++++++++++++++++++++++++++++++++*/ |
255 | |
256 | static int profileType_function(const char *_tag_,int _type_,const char *name,const char *transport) |
257 | { |
258 | if(_type_&XMLPARSE_TAG_START) |
259 | { |
260 | Transport transporttype; |
261 | int i; |
262 | |
263 | XMLPARSE_ASSERT_STRING(_tag_,name); |
264 | XMLPARSE_ASSERT_STRING(_tag_,transport); |
265 | |
266 | for(i=0;i<nloaded_profiles;i++) |
267 | if(!strcmp(name,loaded_profiles[i]->name)) |
268 | XMLPARSE_MESSAGE(_tag_,"profile name must be unique"); |
269 | |
270 | transporttype=TransportType(transport); |
271 | |
272 | if(transporttype==Transport_None) |
273 | XMLPARSE_INVALID(_tag_,transport); |
274 | |
275 | if((nloaded_profiles%16)==0) |
276 | loaded_profiles=(Profile**)realloc((void*)loaded_profiles,(nloaded_profiles+16)*sizeof(Profile*)); |
277 | |
278 | nloaded_profiles++; |
279 | |
280 | loaded_profiles[nloaded_profiles-1]=(Profile*)calloc(1,sizeof(Profile)); |
281 | |
282 | loaded_profiles[nloaded_profiles-1]->name=strcpy(malloc(strlen(name)+1),name); |
283 | loaded_profiles[nloaded_profiles-1]->transport=transporttype; |
284 | } |
285 | |
286 | return(0); |
287 | } |
288 | |
289 | |
290 | /*++++++++++++++++++++++++++++++++++++++ |
291 | The function that is called when the speedsType XSD type is seen |
292 | |
293 | int speedsType_function Returns 0 if no error occured or something else otherwise. |
294 | |
295 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
296 | |
297 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
298 | ++++++++++++++++++++++++++++++++++++++*/ |
299 | |
300 | //static int speedsType_function(const char *_tag_,int _type_) |
301 | //{ |
302 | // return(0); |
303 | //} |
304 | |
305 | |
306 | /*++++++++++++++++++++++++++++++++++++++ |
307 | The function that is called when the preferencesType XSD type is seen |
308 | |
309 | int preferencesType_function Returns 0 if no error occured or something else otherwise. |
310 | |
311 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
312 | |
313 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
314 | ++++++++++++++++++++++++++++++++++++++*/ |
315 | |
316 | //static int preferencesType_function(const char *_tag_,int _type_) |
317 | //{ |
318 | // return(0); |
319 | //} |
320 | |
321 | |
322 | /*++++++++++++++++++++++++++++++++++++++ |
323 | The function that is called when the propertiesType XSD type is seen |
324 | |
325 | int propertiesType_function Returns 0 if no error occured or something else otherwise. |
326 | |
327 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
328 | |
329 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
330 | ++++++++++++++++++++++++++++++++++++++*/ |
331 | |
332 | //static int propertiesType_function(const char *_tag_,int _type_) |
333 | //{ |
334 | // return(0); |
335 | //} |
336 | |
337 | |
338 | /*++++++++++++++++++++++++++++++++++++++ |
339 | The function that is called when the restrictionsType XSD type is seen |
340 | |
341 | int restrictionsType_function Returns 0 if no error occured or something else otherwise. |
342 | |
343 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
344 | |
345 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
346 | ++++++++++++++++++++++++++++++++++++++*/ |
347 | |
348 | //static int restrictionsType_function(const char *_tag_,int _type_) |
349 | //{ |
350 | // return(0); |
351 | //} |
352 | |
353 | |
354 | /*++++++++++++++++++++++++++++++++++++++ |
355 | The function that is called when the speedType XSD type is seen |
356 | |
357 | int speedType_function Returns 0 if no error occured or something else otherwise. |
358 | |
359 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
360 | |
361 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
362 | |
363 | const char *highway The contents of the 'highway' attribute (or NULL if not defined). |
364 | |
365 | const char *kph The contents of the 'kph' attribute (or NULL if not defined). |
366 | ++++++++++++++++++++++++++++++++++++++*/ |
367 | |
368 | static int speedType_function(const char *_tag_,int _type_,const char *highway,const char *kph) |
369 | { |
370 | if(_type_&XMLPARSE_TAG_START) |
371 | { |
372 | double speed; |
373 | Highway highwaytype; |
374 | |
375 | XMLPARSE_ASSERT_STRING(_tag_,highway); |
376 | |
377 | highwaytype=HighwayType(highway); |
378 | |
379 | if(highwaytype==Highway_None) |
380 | XMLPARSE_INVALID(_tag_,highway); |
381 | |
382 | XMLPARSE_ASSERT_FLOATING(_tag_,kph); speed=atof(kph); |
383 | |
384 | loaded_profiles[nloaded_profiles-1]->speed[highwaytype]=kph_to_speed(speed); |
385 | } |
386 | |
387 | return(0); |
388 | } |
389 | |
390 | |
391 | /*++++++++++++++++++++++++++++++++++++++ |
392 | The function that is called when the preferenceType XSD type is seen |
393 | |
394 | int preferenceType_function Returns 0 if no error occured or something else otherwise. |
395 | |
396 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
397 | |
398 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
399 | |
400 | const char *highway The contents of the 'highway' attribute (or NULL if not defined). |
401 | |
402 | const char *percent The contents of the 'percent' attribute (or NULL if not defined). |
403 | ++++++++++++++++++++++++++++++++++++++*/ |
404 | |
405 | static int preferenceType_function(const char *_tag_,int _type_,const char *highway,const char *percent) |
406 | { |
407 | if(_type_&XMLPARSE_TAG_START) |
408 | { |
409 | Highway highwaytype; |
410 | double p; |
411 | |
412 | XMLPARSE_ASSERT_STRING(_tag_,highway); |
413 | |
414 | highwaytype=HighwayType(highway); |
415 | |
416 | if(highwaytype==Highway_None) |
417 | XMLPARSE_INVALID(_tag_,highway); |
418 | |
419 | XMLPARSE_ASSERT_FLOATING(_tag_,percent); p=atof(percent); |
420 | |
421 | loaded_profiles[nloaded_profiles-1]->highway[highwaytype]=(score_t)p; |
422 | } |
423 | |
424 | return(0); |
425 | } |
426 | |
427 | |
428 | /*++++++++++++++++++++++++++++++++++++++ |
429 | The function that is called when the propertyType XSD type is seen |
430 | |
431 | int propertyType_function Returns 0 if no error occured or something else otherwise. |
432 | |
433 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
434 | |
435 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
436 | |
437 | const char *type The contents of the 'type' attribute (or NULL if not defined). |
438 | |
439 | const char *percent The contents of the 'percent' attribute (or NULL if not defined). |
440 | ++++++++++++++++++++++++++++++++++++++*/ |
441 | |
442 | static int propertyType_function(const char *_tag_,int _type_,const char *type,const char *percent) |
443 | { |
444 | if(_type_&XMLPARSE_TAG_START) |
445 | { |
446 | Property property; |
447 | double p; |
448 | |
449 | XMLPARSE_ASSERT_STRING(_tag_,type); |
450 | |
451 | property=PropertyType(type); |
452 | |
453 | if(property==Property_None) |
454 | XMLPARSE_INVALID(_tag_,type); |
455 | |
456 | XMLPARSE_ASSERT_FLOATING(_tag_,percent); p=atof(percent); |
457 | |
458 | loaded_profiles[nloaded_profiles-1]->props_yes[property]=(score_t)p; |
459 | } |
460 | |
461 | return(0); |
462 | } |
463 | |
464 | |
465 | /*++++++++++++++++++++++++++++++++++++++ |
466 | The function that is called when the onewayType XSD type is seen |
467 | |
468 | int onewayType_function Returns 0 if no error occured or something else otherwise. |
469 | |
470 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
471 | |
472 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
473 | |
474 | const char *obey The contents of the 'obey' attribute (or NULL if not defined). |
475 | ++++++++++++++++++++++++++++++++++++++*/ |
476 | |
477 | static int onewayType_function(const char *_tag_,int _type_,const char *obey) |
478 | { |
479 | if(_type_&XMLPARSE_TAG_START) |
480 | { |
481 | int o; |
482 | |
483 | XMLPARSE_ASSERT_INTEGER(_tag_,obey); o=atoi(obey); |
484 | |
485 | loaded_profiles[nloaded_profiles-1]->oneway=!!o; |
486 | } |
487 | |
488 | return(0); |
489 | } |
490 | |
491 | |
492 | /*++++++++++++++++++++++++++++++++++++++ |
493 | The function that is called when the turnsType XSD type is seen |
494 | |
495 | int turnsType_function Returns 0 if no error occured or something else otherwise. |
496 | |
497 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
498 | |
499 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
500 | |
501 | const char *obey The contents of the 'obey' attribute (or NULL if not defined). |
502 | ++++++++++++++++++++++++++++++++++++++*/ |
503 | |
504 | static int turnsType_function(const char *_tag_,int _type_,const char *obey) |
505 | { |
506 | if(_type_&XMLPARSE_TAG_START) |
507 | { |
508 | int o; |
509 | |
510 | XMLPARSE_ASSERT_INTEGER(_tag_,obey); o=atoi(obey); |
511 | |
512 | loaded_profiles[nloaded_profiles-1]->turns=!!o; |
513 | } |
514 | |
515 | return(0); |
516 | } |
517 | |
518 | |
519 | /*++++++++++++++++++++++++++++++++++++++ |
520 | The function that is called when the weightType XSD type is seen |
521 | |
522 | int weightType_function Returns 0 if no error occured or something else otherwise. |
523 | |
524 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
525 | |
526 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
527 | |
528 | const char *limit The contents of the 'limit' attribute (or NULL if not defined). |
529 | ++++++++++++++++++++++++++++++++++++++*/ |
530 | |
531 | static int weightType_function(const char *_tag_,int _type_,const char *limit) |
532 | { |
533 | if(_type_&XMLPARSE_TAG_START) |
534 | { |
535 | double l; |
536 | |
537 | XMLPARSE_ASSERT_FLOATING(_tag_,limit); l=atof(limit); |
538 | |
539 | loaded_profiles[nloaded_profiles-1]->weight=tonnes_to_weight(l); |
540 | } |
541 | |
542 | return(0); |
543 | } |
544 | |
545 | |
546 | /*++++++++++++++++++++++++++++++++++++++ |
547 | The function that is called when the heightType XSD type is seen |
548 | |
549 | int heightType_function Returns 0 if no error occured or something else otherwise. |
550 | |
551 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
552 | |
553 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
554 | |
555 | const char *limit The contents of the 'limit' attribute (or NULL if not defined). |
556 | ++++++++++++++++++++++++++++++++++++++*/ |
557 | |
558 | static int heightType_function(const char *_tag_,int _type_,const char *limit) |
559 | { |
560 | if(_type_&XMLPARSE_TAG_START) |
561 | { |
562 | double l; |
563 | |
564 | XMLPARSE_ASSERT_FLOATING(_tag_,limit); l=atof(limit); |
565 | |
566 | loaded_profiles[nloaded_profiles-1]->height=metres_to_height(l); |
567 | } |
568 | |
569 | return(0); |
570 | } |
571 | |
572 | |
573 | /*++++++++++++++++++++++++++++++++++++++ |
574 | The function that is called when the widthType XSD type is seen |
575 | |
576 | int widthType_function Returns 0 if no error occured or something else otherwise. |
577 | |
578 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
579 | |
580 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
581 | |
582 | const char *limit The contents of the 'limit' attribute (or NULL if not defined). |
583 | ++++++++++++++++++++++++++++++++++++++*/ |
584 | |
585 | static int widthType_function(const char *_tag_,int _type_,const char *limit) |
586 | { |
587 | if(_type_&XMLPARSE_TAG_START) |
588 | { |
589 | double l; |
590 | |
591 | XMLPARSE_ASSERT_FLOATING(_tag_,limit); l=atof(limit); |
592 | |
593 | loaded_profiles[nloaded_profiles-1]->width=metres_to_width(l); |
594 | } |
595 | |
596 | return(0); |
597 | } |
598 | |
599 | |
600 | /*++++++++++++++++++++++++++++++++++++++ |
601 | The function that is called when the lengthType XSD type is seen |
602 | |
603 | int lengthType_function Returns 0 if no error occured or something else otherwise. |
604 | |
605 | const char *_tag_ Set to the name of the element tag that triggered this function call. |
606 | |
607 | int _type_ Set to XMLPARSE_TAG_START at the start of a tag and/or XMLPARSE_TAG_END at the end of a tag. |
608 | |
609 | const char *limit The contents of the 'limit' attribute (or NULL if not defined). |
610 | ++++++++++++++++++++++++++++++++++++++*/ |
611 | |
612 | static int lengthType_function(const char *_tag_,int _type_,const char *limit) |
613 | { |
614 | if(_type_&XMLPARSE_TAG_START) |
615 | { |
616 | double l; |
617 | |
618 | XMLPARSE_ASSERT_FLOATING(_tag_,limit); l=atof(limit); |
619 | |
620 | loaded_profiles[nloaded_profiles-1]->length=metres_to_length(l); |
621 | } |
622 | |
623 | return(0); |
624 | } |
625 | |
626 | |
627 | /*++++++++++++++++++++++++++++++++++++++ |
628 | The XML profile parser. |
629 | |
630 | int ParseXMLProfiles Returns 0 if OK or something else in case of an error. |
631 | |
632 | const char *filename The name of the file to read. |
633 | ++++++++++++++++++++++++++++++++++++++*/ |
634 | |
635 | int ParseXMLProfiles(const char *filename) |
636 | { |
637 | int fd; |
638 | int retval; |
639 | |
640 | if(!ExistsFile(filename)) |
641 | { |
642 | fprintf(stderr,"Error: Specified profiles file '%s' does not exist.\n",filename); |
643 | return(1); |
644 | } |
645 | |
646 | fd=OpenFile(filename); |
647 | |
648 | retval=ParseXML(fd,xml_toplevel_tags,XMLPARSE_UNKNOWN_ATTR_ERRNONAME); |
649 | |
650 | CloseFile(fd); |
651 | |
652 | if(retval) |
653 | { |
654 | FreeXMLProfiles(); |
655 | |
656 | return(1); |
657 | } |
658 | |
659 | return(0); |
660 | } |
661 | |
662 | |
663 | /*++++++++++++++++++++++++++++++++++++++ |
664 | Free the memory allocated when reading the profiles. |
665 | ++++++++++++++++++++++++++++++++++++++*/ |
666 | |
667 | void FreeXMLProfiles(void) |
668 | { |
669 | int i; |
670 | |
671 | if(!loaded_profiles) |
672 | return; |
673 | |
674 | for(i=0;i<nloaded_profiles;i++) |
675 | { |
676 | if(loaded_profiles[i]->name) |
677 | free(loaded_profiles[i]->name); |
678 | |
679 | free(loaded_profiles[i]); |
680 | } |
681 | |
682 | free(loaded_profiles); |
683 | |
684 | loaded_profiles=NULL; |
685 | nloaded_profiles=0; |
686 | } |
687 | |
688 | |
689 | /*++++++++++++++++++++++++++++++++++++++ |
690 | Get a named profile. |
691 | |
692 | Profile *GetProfile Returns a pointer to the profile. |
693 | |
694 | const char *name The name of the profile. |
695 | ++++++++++++++++++++++++++++++++++++++*/ |
696 | |
697 | Profile *GetProfile(const char *name) |
698 | { |
699 | int i; |
700 | |
701 | for(i=0;i<nloaded_profiles;i++) |
702 | if(!strcmp(loaded_profiles[i]->name,name)) |
703 | return(loaded_profiles[i]); |
704 | |
705 | return(NULL); |
706 | } |
707 | |
708 | |
709 | /*++++++++++++++++++++++++++++++++++++++ |
710 | Update a profile with the highway preference scaling factors. |
711 | |
712 | int UpdateProfile Returns 1 in case of a problem. |
713 | |
714 | Profile *profile The profile to be updated. |
715 | |
716 | Ways *ways The set of ways to use. |
717 | ++++++++++++++++++++++++++++++++++++++*/ |
718 | |
719 | int UpdateProfile(Profile *profile,Ways *ways) |
720 | { |
721 | score_t hmax=0; |
722 | int i; |
723 | |
724 | /* Fix up the allowed transport types. */ |
725 | |
726 | profile->allow=TRANSPORTS(profile->transport); |
727 | |
728 | if(!(profile->allow & ways->file.allow)) |
729 | return(1); |
730 | |
731 | /* Normalise the highway preferences into the range ~0 -> 1 */ |
732 | |
733 | for(i=1;i<Highway_Count;i++) |
734 | { |
735 | if(profile->highway[i]<0) |
736 | profile->highway[i]=0; |
737 | |
738 | if(profile->highway[i]>hmax) |
739 | hmax=profile->highway[i]; |
740 | } |
741 | |
742 | if(hmax==0) |
743 | return(1); |
744 | |
745 | for(i=1;i<Highway_Count;i++) |
746 | { |
747 | profile->highway[i]/=hmax; |
748 | |
749 | if(profile->highway[i]<0.0001f) |
750 | profile->highway[i]=0.0001f; |
751 | } |
752 | |
753 | /* Normalise the property preferences into the range ~0 -> 1 */ |
754 | |
755 | for(i=1;i<Property_Count;i++) |
756 | { |
757 | if(profile->props_yes[i]<0) |
758 | profile->props_yes[i]=0; |
759 | |
760 | if(profile->props_yes[i]>100) |
761 | profile->props_yes[i]=100; |
762 | |
763 | profile->props_yes[i]/=100; |
764 | profile->props_no [i] =1-profile->props_yes[i]; |
765 | |
766 | /* Squash the properties; selecting 60% preference without the sqrt() allows |
767 | routes 50% longer on highways with the property compared to ones without. |
768 | With the sqrt() function the ratio is only 22% allowing finer control. */ |
769 | |
770 | profile->props_yes[i]=(score_t)sqrt(profile->props_yes[i]); |
771 | profile->props_no [i]=(score_t)sqrt(profile->props_no[i] ); |
772 | |
773 | if(profile->props_yes[i]<0.01f) |
774 | profile->props_yes[i]=0.01f; |
775 | |
776 | if(profile->props_no[i]<0.01f) |
777 | profile->props_no[i]=0.01f; |
778 | } |
779 | |
780 | /* Find the fastest preferred speed */ |
781 | |
782 | profile->max_speed=0; |
783 | |
784 | for(i=1;i<Highway_Count;i++) |
785 | if(profile->speed[i]>profile->max_speed) |
786 | profile->max_speed=profile->speed[i]; |
787 | |
788 | if(profile->max_speed==0) |
789 | return(1); |
790 | |
791 | /* Find the most preferred property combination */ |
792 | |
793 | profile->max_pref=1; /* since highway prefs were normalised to 1 */ |
794 | |
795 | for(i=1;i<Property_Count;i++) |
796 | if(ways->file.props & PROPERTIES(i)) |
797 | { |
798 | if(profile->props_yes[i]>profile->props_no[i]) |
799 | profile->max_pref*=profile->props_yes[i]; |
800 | else |
801 | profile->max_pref*=profile->props_no[i]; |
802 | } |
803 | |
804 | return(0); |
805 | } |
806 | |
807 | |
808 | /*++++++++++++++++++++++++++++++++++++++ |
809 | Print out a profile. |
810 | |
811 | const Profile *profile The profile to print. |
812 | ++++++++++++++++++++++++++++++++++++++*/ |
813 | |
814 | void PrintProfile(const Profile *profile) |
815 | { |
816 | int i; |
817 | |
818 | printf("Profile\n=======\n"); |
819 | |
820 | printf("\n"); |
821 | |
822 | printf("Transport: %s\n",TransportName(profile->transport)); |
823 | |
824 | printf("\n"); |
825 | |
826 | for(i=1;i<Highway_Count;i++) |
827 | printf("Highway %-12s: %3d%%\n",HighwayName(i),(int)profile->highway[i]); |
828 | |
829 | printf("\n"); |
830 | |
831 | for(i=1;i<Highway_Count;i++) |
832 | if(profile->highway[i]) |
833 | printf("Speed on %-12s: %3d km/h / %2.0f mph\n",HighwayName(i),profile->speed[i],(double)profile->speed[i]/1.6); |
834 | |
835 | printf("\n"); |
836 | |
837 | for(i=1;i<Property_Count;i++) |
838 | printf("Highway property %-12s: %3d%%\n",PropertyName(i),(int)profile->props_yes[i]); |
839 | |
840 | printf("\n"); |
841 | |
842 | printf("Obey one-way : %s\n",profile->oneway?"yes":"no"); |
843 | printf("Obey turns : %s\n",profile->turns?"yes":"no"); |
844 | printf("Minimum weight: %.1f tonnes\n",weight_to_tonnes(profile->weight)); |
845 | printf("Minimum height: %.1f metres\n",height_to_metres(profile->height)); |
846 | printf("Minimum width : %.1f metres\n",width_to_metres(profile->width)); |
847 | printf("Minimum length: %.1f metres\n",length_to_metres(profile->length)); |
848 | } |
849 | |
850 | |
851 | /*++++++++++++++++++++++++++++++++++++++ |
852 | Print out all of the loaded profiles as XML for use as program input. |
853 | ++++++++++++++++++++++++++++++++++++++*/ |
854 | |
855 | void PrintProfilesXML(void) |
856 | { |
857 | int i,j; |
858 | char *padding=" "; |
859 | |
860 | printf("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); |
861 | printf("\n"); |
862 | |
863 | printf("<routino-profiles xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"routino-profiles.xsd\">\n"); |
864 | printf("\n"); |
865 | |
866 | for(j=0;j<nloaded_profiles;j++) |
867 | { |
868 | printf(" <profile name=\"%s\" transport=\"%s\">\n",loaded_profiles[j]->name,TransportName(loaded_profiles[j]->transport)); |
869 | |
870 | printf(" <speeds>\n"); |
871 | for(i=1;i<Highway_Count;i++) |
872 | printf(" <speed highway=\"%s\"%s kph=\"%d\" />\n",HighwayName(i),padding+3+strlen(HighwayName(i)),loaded_profiles[j]->speed[i]); |
873 | printf(" </speeds>\n"); |
874 | |
875 | printf(" <preferences>\n"); |
876 | for(i=1;i<Highway_Count;i++) |
877 | printf(" <preference highway=\"%s\"%s percent=\"%.0f\" />\n",HighwayName(i),padding+3+strlen(HighwayName(i)),loaded_profiles[j]->highway[i]); |
878 | printf(" </preferences>\n"); |
879 | |
880 | printf(" <properties>\n"); |
881 | for(i=1;i<Property_Count;i++) |
882 | printf(" <property type=\"%s\"%s percent=\"%.0f\" />\n",PropertyName(i),padding+6+strlen(PropertyName(i)),loaded_profiles[j]->props_yes[i]); |
883 | printf(" </properties>\n"); |
884 | |
885 | printf(" <restrictions>\n"); |
886 | printf(" <oneway obey=\"%d\" /> \n",loaded_profiles[j]->oneway); |
887 | printf(" <turns obey=\"%d\" /> \n",loaded_profiles[j]->turns); |
888 | printf(" <weight limit=\"%.1f\" />\n",weight_to_tonnes(loaded_profiles[j]->weight)); |
889 | printf(" <height limit=\"%.1f\" />\n",height_to_metres(loaded_profiles[j]->height)); |
890 | printf(" <width limit=\"%.1f\" />\n",width_to_metres(loaded_profiles[j]->width)); |
891 | printf(" <length limit=\"%.1f\" />\n",length_to_metres(loaded_profiles[j]->length)); |
892 | printf(" </restrictions>\n"); |
893 | |
894 | printf(" </profile>\n"); |
895 | printf("\n"); |
896 | } |
897 | |
898 | printf("</routino-profiles>\n"); |
899 | } |
900 | |
901 | |
902 | /*++++++++++++++++++++++++++++++++++++++ |
903 | Print out all of the loaded profiles as JavaScript Object Notation for use in a web page. |
904 | ++++++++++++++++++++++++++++++++++++++*/ |
905 | |
906 | void PrintProfilesJSON(void) |
907 | { |
908 | int i,j; |
909 | |
910 | printf("var routino={ // contains all default Routino options (generated using \"--help-profile-json\").\n"); |
911 | printf("\n"); |
912 | |
913 | printf(" // Default transport type\n"); |
914 | printf(" transport: \"motorcar\",\n"); |
915 | printf("\n"); |
916 | |
917 | printf(" // Transport types\n"); |
918 | printf(" transports: { "); |
919 | for(j=0;j<nloaded_profiles;j++) |
920 | printf("%s%s: %d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),j+1); |
921 | printf(" },\n"); |
922 | printf("\n"); |
923 | |
924 | printf(" // Highway types\n"); |
925 | printf(" highways: { "); |
926 | for(i=1;i<Highway_Count;i++) |
927 | printf("%s%s: %d",i==1?"":", ",HighwayName(i),i); |
928 | printf(" },\n"); |
929 | printf("\n"); |
930 | |
931 | printf(" // Property types\n"); |
932 | printf(" properties: { "); |
933 | for(i=1;i<Property_Count;i++) |
934 | printf("%s%s: %d",i==1?"":", ",PropertyName(i),i); |
935 | printf(" },\n"); |
936 | printf("\n"); |
937 | |
938 | printf(" // Restriction types\n"); |
939 | printf(" restrictions: { oneway: 1, turns: 2, weight: 3, height: 4, width: 5, length: 6 },\n"); |
940 | printf("\n"); |
941 | |
942 | printf(" // Allowed highways\n"); |
943 | printf(" profile_highway: {\n"); |
944 | for(i=1;i<Highway_Count;i++) |
945 | { |
946 | printf(" %12s: { ",HighwayName(i)); |
947 | for(j=0;j<nloaded_profiles;j++) |
948 | printf("%s%s: %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->highway[i]); |
949 | printf(" }%s\n",i==(Highway_Count-1)?"":","); |
950 | } |
951 | printf(" },\n"); |
952 | printf("\n"); |
953 | |
954 | printf(" // Speed limits\n"); |
955 | printf(" profile_speed: {\n"); |
956 | for(i=1;i<Highway_Count;i++) |
957 | { |
958 | printf(" %12s: { ",HighwayName(i)); |
959 | for(j=0;j<nloaded_profiles;j++) |
960 | printf("%s%s: %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->speed[i]); |
961 | printf(" }%s\n",i==(Highway_Count-1)?"":","); |
962 | } |
963 | printf(" },\n"); |
964 | printf("\n"); |
965 | |
966 | printf(" // Highway properties\n"); |
967 | printf(" profile_property: {\n"); |
968 | for(i=1;i<Property_Count;i++) |
969 | { |
970 | printf(" %13s: { ",PropertyName(i)); |
971 | for(j=0;j<nloaded_profiles;j++) |
972 | printf("%s%s: %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->props_yes[i]); |
973 | printf(" }%s\n",i==(Property_Count-1)?"":","); |
974 | } |
975 | printf(" },\n"); |
976 | printf("\n"); |
977 | |
978 | printf(" // Restrictions\n"); |
979 | printf(" profile_restrictions: {\n"); |
980 | printf(" %12s: { ","oneway"); |
981 | for(j=0;j<nloaded_profiles;j++) |
982 | printf("%s%s: %4d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->oneway); |
983 | printf(" },\n"); |
984 | printf(" %12s: { ","turns"); |
985 | for(j=0;j<nloaded_profiles;j++) |
986 | printf("%s%s: %4d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->turns); |
987 | printf(" },\n"); |
988 | printf(" %12s: { ","weight"); |
989 | for(j=0;j<nloaded_profiles;j++) |
990 | printf("%s%s: %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),weight_to_tonnes(loaded_profiles[j]->weight)); |
991 | printf(" },\n"); |
992 | printf(" %12s: { ","height"); |
993 | for(j=0;j<nloaded_profiles;j++) |
994 | printf("%s%s: %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),height_to_metres(loaded_profiles[j]->height)); |
995 | printf(" },\n"); |
996 | printf(" %12s: { ","width"); |
997 | for(j=0;j<nloaded_profiles;j++) |
998 | printf("%s%s: %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),width_to_metres(loaded_profiles[j]->width)); |
999 | printf(" },\n"); |
1000 | printf(" %12s: { ","length"); |
1001 | for(j=0;j<nloaded_profiles;j++) |
1002 | printf("%s%s: %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),length_to_metres(loaded_profiles[j]->length)); |
1003 | printf(" }\n"); |
1004 | printf(" }\n"); |
1005 | printf("\n"); |
1006 | |
1007 | printf("}; // end of routino variable\n"); |
1008 | } |
1009 | |
1010 | |
1011 | /*++++++++++++++++++++++++++++++++++++++ |
1012 | Print out all of the loaded profiles as Perl for use in a web CGI. |
1013 | ++++++++++++++++++++++++++++++++++++++*/ |
1014 | |
1015 | void PrintProfilesPerl(void) |
1016 | { |
1017 | int i,j; |
1018 | |
1019 | printf("$routino={ # contains all default Routino options (generated using \"--help-profile-perl\").\n"); |
1020 | printf("\n"); |
1021 | |
1022 | printf(" # Default transport type\n"); |
1023 | printf(" transport => \"motorcar\",\n"); |
1024 | printf("\n"); |
1025 | |
1026 | printf(" # Transport types\n"); |
1027 | printf(" transports => { "); |
1028 | for(j=0;j<nloaded_profiles;j++) |
1029 | printf("%s%s => %d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),j+1); |
1030 | printf(" },\n"); |
1031 | printf("\n"); |
1032 | |
1033 | printf(" # Highway types\n"); |
1034 | printf(" highways => { "); |
1035 | for(i=1;i<Highway_Count;i++) |
1036 | printf("%s%s => %d",i==1?"":", ",HighwayName(i),i); |
1037 | printf(" },\n"); |
1038 | printf("\n"); |
1039 | |
1040 | printf(" # Property types\n"); |
1041 | printf(" properties => { "); |
1042 | for(i=1;i<Property_Count;i++) |
1043 | printf("%s%s => %d",i==1?"":", ",PropertyName(i),i); |
1044 | printf(" },\n"); |
1045 | printf("\n"); |
1046 | |
1047 | printf(" # Restriction types\n"); |
1048 | printf(" restrictions => { oneway => 1, turns => 2, weight => 3, height => 4, width => 5, length => 6 },\n"); |
1049 | printf("\n"); |
1050 | |
1051 | printf(" # Allowed highways\n"); |
1052 | printf(" profile_highway => {\n"); |
1053 | for(i=1;i<Highway_Count;i++) |
1054 | { |
1055 | printf(" %12s => {",HighwayName(i)); |
1056 | for(j=0;j<nloaded_profiles;j++) |
1057 | printf("%s %s => %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->highway[i]); |
1058 | printf(" }%s\n",i==(Highway_Count-1)?"":","); |
1059 | } |
1060 | printf(" },\n"); |
1061 | printf("\n"); |
1062 | |
1063 | printf(" # Speed limits\n"); |
1064 | printf(" profile_speed => {\n"); |
1065 | for(i=1;i<Highway_Count;i++) |
1066 | { |
1067 | printf(" %12s => {",HighwayName(i)); |
1068 | for(j=0;j<nloaded_profiles;j++) |
1069 | printf("%s %s => %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->speed[i]); |
1070 | printf(" }%s\n",i==(Highway_Count-1)?"":","); |
1071 | } |
1072 | printf(" },\n"); |
1073 | printf("\n"); |
1074 | |
1075 | printf(" # Highway properties\n"); |
1076 | printf(" profile_property => {\n"); |
1077 | for(i=1;i<Property_Count;i++) |
1078 | { |
1079 | printf(" %13s => {",PropertyName(i)); |
1080 | for(j=0;j<nloaded_profiles;j++) |
1081 | printf("%s %s => %3d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),(int)loaded_profiles[j]->props_yes[i]); |
1082 | printf(" }%s\n",i==(Property_Count-1)?"":","); |
1083 | } |
1084 | printf(" },\n"); |
1085 | printf("\n"); |
1086 | |
1087 | printf(" # Restrictions\n"); |
1088 | printf(" profile_restrictions => {\n"); |
1089 | printf(" %12s => {","oneway"); |
1090 | for(j=0;j<nloaded_profiles;j++) |
1091 | printf("%s %s => %4d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->oneway); |
1092 | printf(" },\n"); |
1093 | printf(" %12s => {","turns"); |
1094 | for(j=0;j<nloaded_profiles;j++) |
1095 | printf("%s %s => %4d",j==0?"":", ",TransportName(loaded_profiles[j]->transport),loaded_profiles[j]->turns); |
1096 | printf(" },\n"); |
1097 | printf(" %12s => {","weight"); |
1098 | for(j=0;j<nloaded_profiles;j++) |
1099 | printf("%s %s => %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),weight_to_tonnes(loaded_profiles[j]->weight)); |
1100 | printf(" },\n"); |
1101 | printf(" %12s => {","height"); |
1102 | for(j=0;j<nloaded_profiles;j++) |
1103 | printf("%s %s => %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),height_to_metres(loaded_profiles[j]->height)); |
1104 | printf(" },\n"); |
1105 | printf(" %12s => {","width"); |
1106 | for(j=0;j<nloaded_profiles;j++) |
1107 | printf("%s %s => %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),width_to_metres(loaded_profiles[j]->width)); |
1108 | printf(" },\n"); |
1109 | printf(" %12s => {","length"); |
1110 | for(j=0;j<nloaded_profiles;j++) |
1111 | printf("%s %s => %4.1f",j==0?"":", ",TransportName(loaded_profiles[j]->transport),length_to_metres(loaded_profiles[j]->length)); |
1112 | printf(" }\n"); |
1113 | printf(" }\n"); |
1114 | printf("\n"); |
1115 | |
1116 | printf("}; # end of routino variable\n"); |
1117 | } |
Properties
Name | Value |
---|---|
cvs:description | Definition of built-in profiles and other functions. |