/[zanavi_public1]/navit/navit/map/shapefile/shapefile.c
ZANavi

Contents of /navit/navit/map/shapefile/shapefile.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 20026 byte(s)
import files
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include <stdlib.h>
21 #include <glib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <math.h>
25 #include "config.h"
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #include "debug.h"
30 #include "plugin.h"
31 #include "projection.h"
32 #include "item.h"
33 #include "map.h"
34 #include "maptype.h"
35 #include "attr.h"
36 #include "transform.h"
37 #include "file.h"
38 #include "shapefil.h"
39
40
41 #define IS_ARC(x) ((x).nSHPType == SHPT_ARC || (x).nSHPType == SHPT_ARCZ || (x).nSHPType == SHPT_ARCM)
42 #define IS_POLYGON(x) ((x).nSHPType == SHPT_POLYGON || (x).nSHPType == SHPT_POLYGONZ || (x).nSHPType == SHPT_POLYGONM)
43
44 struct map_priv {
45 int id;
46 char *filename;
47 char *charset;
48 SHPHandle hSHP;
49 DBFHandle hDBF;
50 int nShapeType, nEntities, nFields;
51 double adfMinBound[4], adfMaxBound[4];
52 struct longest_match *lm;
53 char *dbfmap_data;
54 struct coord offset;
55 enum projection pro;
56 int flags;
57 };
58
59
60 struct map_rect_priv {
61 struct map_selection *sel;
62 struct map_priv *m;
63 struct item item;
64 int idx;
65 int cidx,cidx_rewind;
66 int part,part_rewind;
67 int aidx;
68 enum attr_type anext;
69 SHPObject *psShape;
70 char *str;
71 char *line;
72 int attr_pos;
73 struct attr *attr;
74 };
75
76 static void
77 map_destroy_shapefile(struct map_priv *m)
78 {
79 dbg(1,"map_destroy_shapefile\n");
80 g_free(m);
81 }
82
83 static void
84 shapefile_coord_rewind(void *priv_data)
85 {
86 struct map_rect_priv *mr=priv_data;
87 mr->cidx=mr->cidx_rewind;
88 mr->part=mr->part_rewind;
89 }
90
91 static void
92 shapefile_coord(struct map_rect_priv *mr, int idx, struct coord *c)
93 {
94 SHPObject *psShape=mr->psShape;
95 struct coord cs;
96 struct coord_geo g;
97
98 if (!mr->m->pro) {
99 g.lng=psShape->padfX[idx]+mr->m->offset.x;
100 g.lat=psShape->padfY[idx]+mr->m->offset.y;
101 transform_from_geo(projection_mg, &g, c);
102 } else {
103 cs.x=psShape->padfX[idx]+mr->m->offset.x;
104 cs.y=psShape->padfY[idx]+mr->m->offset.y;
105 transform_from_to(&cs, mr->m->pro, c, projection_mg);
106 }
107 }
108
109 static int
110 shapefile_coord_get(void *priv_data, struct coord *c, int count)
111 {
112 struct map_rect_priv *mr=priv_data;
113 int ret=0;
114 int idx;
115
116 SHPObject *psShape=mr->psShape;
117 while (count) {
118 idx=mr->cidx;
119 if (idx >= psShape->nVertices)
120 break;
121 if (mr->part+1 < psShape->nParts && idx == psShape->panPartStart[mr->part+1]) {
122 if (IS_POLYGON(*psShape)) {
123 mr->part++;
124 shapefile_coord(mr, 0, c);
125 } else if (IS_ARC(*psShape)) {
126 break;
127 } else {
128 dbg_assert("Neither POLYGON or ARC and has parts" == NULL);
129 }
130 } else {
131 shapefile_coord(mr, idx, c);
132 mr->cidx++;
133 }
134 ret++;
135 c++;
136 count--;
137 }
138 return ret;
139 }
140
141 static void
142 shapefile_attr_rewind(void *priv_data)
143 {
144 struct map_rect_priv *mr=priv_data;
145 mr->aidx=0;
146 mr->attr_pos=0;
147 if (mr->m->flags & 1)
148 mr->anext=attr_none;
149 else
150 mr->anext=attr_debug;
151 }
152
153
154 struct longest_match_list_item {
155 void *data;
156 int match_idx_count;
157 int *match_idx;
158 };
159
160 struct longest_match_list {
161 GList *longest_match_list_items;
162 };
163
164
165 struct longest_match {
166 GHashTable *match_hash;
167 char *match_present;
168 int match_present_count;
169 GList *longest_match_lists;
170 int longest_match_list_count;
171 };
172
173 static void
174 longest_match_add_match(struct longest_match *lm, struct longest_match_list_item *lmi, char *match)
175 {
176 int idx;
177 if (!(idx=(int)(long)g_hash_table_lookup(lm->match_hash, match))) {
178 idx=lm->match_present_count++;
179 lm->match_present=g_renew(char, lm->match_present, lm->match_present_count);
180 g_hash_table_insert(lm->match_hash, g_strdup(match), (gpointer)(long)idx);
181 }
182 lmi->match_idx=g_renew(int, lmi->match_idx, lmi->match_idx_count+1);
183 lmi->match_idx[lmi->match_idx_count++]=idx;
184 }
185
186 static void
187 longest_match_item_destroy(struct longest_match_list_item *lmi, long flags)
188 {
189 if (!lmi)
190 return;
191 if (flags & 2) {
192 g_free(lmi->data);
193 }
194 g_free(lmi->match_idx);
195 g_free(lmi);
196 }
197
198 static struct longest_match_list_item *
199 longest_match_item_new(struct longest_match_list *lml, void *data)
200 {
201 struct longest_match_list_item *ret=g_new0(struct longest_match_list_item,1);
202 lml->longest_match_list_items=g_list_append(lml->longest_match_list_items, ret);
203 ret->data=data;
204
205 return ret;
206 }
207
208 static struct longest_match_list *
209 longest_match_list_new(struct longest_match *lm)
210 {
211 struct longest_match_list *ret=g_new0(struct longest_match_list,1);
212 lm->longest_match_lists=g_list_append(lm->longest_match_lists, ret);
213 return ret;
214 }
215
216 static void
217 longest_match_list_destroy(struct longest_match_list *lml, long flags)
218 {
219 if (!lml)
220 return;
221 if (flags & 1) {
222 g_list_foreach(lml->longest_match_list_items, (GFunc)longest_match_item_destroy, (gpointer)flags);
223 g_list_free(lml->longest_match_list_items);
224 }
225 g_free(lml);
226 }
227
228 static struct longest_match_list *
229 longest_match_get_list(struct longest_match *lm, int list)
230 {
231 GList *l=lm->longest_match_lists;
232 while (l && list > 0) {
233 l=g_list_next(l);
234 list++;
235 }
236 if (l)
237 return l->data;
238 return NULL;
239 }
240
241 static struct longest_match *
242 longest_match_new(void)
243 {
244 struct longest_match *ret=g_new0(struct longest_match,1);
245 ret->match_hash=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
246 ret->match_present_count=1;
247 return ret;
248 }
249
250 static void
251 longest_match_destroy(struct longest_match *lm, long flags)
252 {
253 if (!lm)
254 return;
255 if (flags & 1) {
256 g_list_foreach(lm->longest_match_lists, (GFunc)longest_match_list_destroy, (gpointer)flags);
257 g_list_free(lm->longest_match_lists);
258 }
259 g_hash_table_destroy(lm->match_hash);
260 g_free(lm->match_present);
261 g_free(lm);
262 }
263
264 static void
265 longest_match_clear(struct longest_match *lm)
266 {
267 if (lm->match_present)
268 memset(lm->match_present, 0, lm->match_present_count);
269 }
270
271 static void
272 longest_match_add_key_value(struct longest_match *lm, char *k, char *v)
273 {
274 char* buffer=g_alloca(strlen(k)+strlen(v)+2);
275 int idx;
276
277 strcpy(buffer,"*=*");
278 if ((idx=(int)(long)g_hash_table_lookup(lm->match_hash, buffer)))
279 lm->match_present[idx]=1;
280
281 sprintf(buffer,"%s=*", k);
282 if ((idx=(int)(long)g_hash_table_lookup(lm->match_hash, buffer)))
283 lm->match_present[idx]=2;
284
285 sprintf(buffer,"*=%s", v);
286 if ((idx=(int)(long)g_hash_table_lookup(lm->match_hash, buffer)))
287 lm->match_present[idx]=2;
288
289 sprintf(buffer,"%s=%s", k, v);
290 if ((idx=(int)(long)g_hash_table_lookup(lm->match_hash, buffer)))
291 lm->match_present[idx]=4;
292 }
293
294 static int
295 longest_match_list_find(struct longest_match *lm, struct longest_match_list *lml, void **list, int max_list_len)
296 {
297 int j,longest=0,ret=0,sum,val;
298 struct longest_match_list_item *curr;
299 GList *l=lml->longest_match_list_items;
300
301
302 while (l) {
303 sum=0;
304 curr=l->data;
305 for (j = 0 ; j < curr->match_idx_count ; j++) {
306 val=lm->match_present[curr->match_idx[j]];
307 if (val)
308 sum+=val;
309 else {
310 sum=-1;
311 break;
312 }
313 }
314 if (sum > longest) {
315 longest=sum;
316 ret=0;
317 }
318 if (sum > 0 && sum == longest && ret < max_list_len)
319 list[ret++]=curr->data;
320 l=g_list_next(l);
321 }
322 return ret;
323 }
324
325
326 static void
327 build_match(struct longest_match *lm, struct longest_match_list *lml, char *line)
328 {
329 struct longest_match_list_item *lmli;
330 char *kvl=NULL,*i=NULL,*p,*kv;
331 dbg(1,"line=%s\n",line);
332 kvl=line;
333 p=strchr(line,'\t');
334 if (p) {
335 while (*p == '\t')
336 *p++='\0';
337 i=p;
338 }
339 lmli=longest_match_item_new(lml,g_strdup(i));
340 while ((kv=strtok(kvl, ","))) {
341 kvl=NULL;
342 longest_match_add_match(lm, lmli, kv);
343 }
344 }
345
346 static void
347 build_matches(struct map_priv *m,char *matches)
348 {
349 char *matches2=g_strdup(matches);
350 char *l=matches2,*p;
351 struct longest_match_list *lml;
352
353 m->lm=longest_match_new();
354 lml=longest_match_list_new(m->lm);
355 while (l) {
356 p=strchr(l,'\n');
357 if (p)
358 *p++='\0';
359 if (strlen(l))
360 build_match(m->lm,lml,l);
361 l=p;
362 }
363 g_free(matches2);
364 }
365
366 static void
367 process_fields(struct map_priv *m, int id)
368 {
369 int i;
370 char szTitle[12],*pszTypeName,*str;
371 int nWidth, nDecimals;
372
373 for (i = 0 ; i < m->nFields ; i++) {
374
375 switch (DBFGetFieldInfo(m->hDBF, i, szTitle, &nWidth, &nDecimals )) {
376 case FTString:
377 pszTypeName = "String";
378 str=g_strdup(DBFReadStringAttribute( m->hDBF, id, i ));
379 break;
380 case FTInteger:
381 pszTypeName = "Integer";
382 str=g_strdup_printf("%d",DBFReadIntegerAttribute( m->hDBF, id, i ));
383 break;
384 case FTDouble:
385 pszTypeName = "Double";
386 str=g_strdup_printf("%lf",DBFReadDoubleAttribute( m->hDBF, id, i ));
387 break;
388 case FTInvalid:
389 pszTypeName = "Invalid";
390 str=NULL;
391 break;
392 default:
393 pszTypeName = "Unknown";
394 str=NULL;
395 }
396 longest_match_add_key_value(m->lm, szTitle, str);
397 }
398 }
399
400 static int
401 attr_resolve(struct map_rect_priv *mr, enum attr_type attr_type, struct attr *attr)
402 {
403 char name[1024];
404 char value[1024];
405 char szTitle[12];
406 const char *str;
407 char *col,*type=NULL;
408 int i,len, nWidth, nDecimals;
409 if (!mr->line)
410 return 0;
411 if (attr_type != attr_any)
412 type=attr_to_name(attr_type);
413 if (attr_from_line(mr->line,type,&mr->attr_pos,value,name)) {
414 len=strlen(value);
415 if (value[0] == '$' && value[1] == '{' && value[len-1] == '}') {
416 int found=0;
417 value[len-1]='\0';
418 col=value+2;
419 for (i = 0 ; i < mr->m->nFields ; i++) {
420 if (DBFGetFieldInfo(mr->m->hDBF, i, szTitle, &nWidth, &nDecimals ) == FTString && !strcmp(szTitle,col)) {
421 str=DBFReadStringAttribute( mr->m->hDBF, mr->item.id_hi, i);
422 strcpy(value,str);
423 found=1;
424 break;
425 }
426 }
427 if (!found)
428 value[0]='\0';
429 }
430 if (!value[0])
431 return -1;
432 dbg(1,"name=%s value=%s\n",name,value);
433 attr_free(mr->attr);
434 mr->attr=attr_new_from_text(name,value);
435 if (mr->attr) {
436 *attr=*mr->attr;
437 return 1;
438 }
439 return -1;
440 }
441 return 0;
442 }
443
444 static int
445 shapefile_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
446 {
447 struct map_rect_priv *mr=priv_data;
448 struct map_priv *m=mr->m;
449 char szTitle[12],*pszTypeName, *str;
450 int code, ret, nWidth, nDecimals;
451
452 attr->type=attr_type;
453 switch (attr_type) {
454 case attr_any:
455 while ((code=attr_resolve(mr, attr_type, attr))) {
456 if (code == 1)
457 return 1;
458 }
459 while (mr->anext != attr_none) {
460 ret=shapefile_attr_get(priv_data, mr->anext, attr);
461 if (ret)
462 return ret;
463 }
464 return 0;
465 case attr_debug:
466 if (mr->aidx >= m->nFields) {
467 mr->anext=attr_none;
468 return 0;
469 }
470 switch (DBFGetFieldInfo(m->hDBF, mr->aidx, szTitle, &nWidth, &nDecimals )) {
471 case FTString:
472 pszTypeName = "String";
473 str=g_strdup(DBFReadStringAttribute( m->hDBF, mr->item.id_hi, mr->aidx ));
474 break;
475 case FTInteger:
476 pszTypeName = "Integer";
477 str=g_strdup_printf("%d",DBFReadIntegerAttribute( m->hDBF, mr->item.id_hi, mr->aidx ));
478 break;
479 case FTDouble:
480 pszTypeName = "Double";
481 str=g_strdup_printf("%lf",DBFReadDoubleAttribute( m->hDBF, mr->item.id_hi, mr->aidx ));
482 break;
483 case FTInvalid:
484 pszTypeName = "Invalid";
485 str=NULL;
486 break;
487 default:
488 pszTypeName = "Unknown";
489 str=NULL;
490 }
491 g_free(mr->str);
492 mr->str=attr->u.str=g_strdup_printf("%s=%s(%s)",szTitle,str,pszTypeName);
493 g_free(str);
494 mr->aidx++;
495 return 1;
496 default:
497 return (attr_resolve(mr, attr_type, attr) == 1);
498 }
499 }
500
501 static struct item_methods methods_shapefile = {
502 shapefile_coord_rewind,
503 shapefile_coord_get,
504 shapefile_attr_rewind,
505 shapefile_attr_get,
506 };
507
508 static struct map_rect_priv *
509 map_rect_new_shapefile(struct map_priv *map, struct map_selection *sel)
510 {
511 struct map_rect_priv *mr;
512 char *dbfmapfile=g_strdup_printf("%s.dbfmap", map->filename);
513 void *data;
514 struct file *file;
515 int size;
516 int changed=0;
517 if ((file=file_create(dbfmapfile, 0))) {
518 size=file_size(file);
519 data=file_data_read_all(file);
520 if (data) {
521 if (!map->dbfmap_data || size != strlen(map->dbfmap_data) || strncmp(data,map->dbfmap_data,size)) {
522 g_free(map->dbfmap_data);
523 map->dbfmap_data=g_malloc(size+1);
524 memcpy(map->dbfmap_data, data, size);
525 map->dbfmap_data[size]='\0';
526 changed=1;
527 }
528 file_data_free(file, data);
529 }
530 file_destroy(file);
531 } else {
532 dbg(0,"Failed to open %s\n",dbfmapfile);
533 if (map->dbfmap_data) {
534 changed=1;
535 g_free(map->dbfmap_data);
536 map->dbfmap_data=NULL;
537 }
538 }
539 dbg(1,"%s changed %d old %p\n",dbfmapfile,changed,map->dbfmap_data);
540 if (changed) {
541 longest_match_destroy(map->lm,1);
542 map->lm=NULL;
543 if (map->dbfmap_data) {
544 build_matches(map,map->dbfmap_data);
545 }
546 }
547 dbg(1,"map_rect_new_shapefile\n");
548 mr=g_new0(struct map_rect_priv, 1);
549 mr->m=map;
550 mr->idx=0;
551 mr->item.id_lo=0;
552 mr->item.id_hi=0;
553 mr->item.meth=&methods_shapefile;
554 mr->item.priv_data=mr;
555 g_free(dbfmapfile);
556 return mr;
557 }
558
559
560 static void
561 map_rect_destroy_shapefile(struct map_rect_priv *mr)
562 {
563 if (mr->psShape)
564 SHPDestroyObject(mr->psShape);
565 attr_free(mr->attr);
566 g_free(mr->str);
567 g_free(mr);
568 }
569
570 static struct item *
571 map_rect_get_item_shapefile(struct map_rect_priv *mr)
572 {
573 struct map_priv *m=mr->m;
574 void *lines[5];
575 struct longest_match_list *lml;
576 int count;
577 char type[1024];
578
579 if (mr->psShape && IS_ARC(*mr->psShape) && mr->part+1 < mr->psShape->nParts) {
580 mr->part++;
581 mr->part_rewind=mr->part;
582 mr->cidx_rewind=mr->psShape->panPartStart[mr->part];
583 } else {
584 if (mr->idx >= m->nEntities)
585 return NULL;
586 mr->item.id_hi=mr->idx;
587 if (mr->psShape)
588 SHPDestroyObject(mr->psShape);
589 mr->psShape=SHPReadObject(m->hSHP, mr->idx);
590 if (mr->psShape->nVertices > 1)
591 mr->item.type=type_street_unkn;
592 else
593 mr->item.type=type_point_unkn;
594 if (m->lm) {
595 longest_match_clear(m->lm);
596 process_fields(m, mr->idx);
597
598 lml=longest_match_get_list(m->lm, 0);
599 count=longest_match_list_find(m->lm, lml, lines, sizeof(lines)/sizeof(void *));
600 if (count) {
601 mr->line=lines[0];
602 if (attr_from_line(mr->line,"type",NULL,type,NULL)) {
603 dbg(1,"type='%s'\n", type);
604 mr->item.type=item_from_name(type);
605 if (mr->item.type == type_none && strcmp(type,"none"))
606 dbg(0,"Warning: type '%s' unknown\n", type);
607 } else {
608 dbg(0,"failed to get attribute type\n");
609 }
610 } else
611 mr->line=NULL;
612 }
613 mr->idx++;
614 mr->part_rewind=0;
615 mr->cidx_rewind=0;
616 }
617 shapefile_coord_rewind(mr);
618 shapefile_attr_rewind(mr);
619 return &mr->item;
620 }
621
622 static struct item *
623 map_rect_get_item_byid_shapefile(struct map_rect_priv *mr, int id_hi, int id_lo)
624 {
625 mr->idx=id_hi;
626 while (id_lo--) {
627 if (!map_rect_get_item_shapefile(mr))
628 return NULL;
629 }
630 return map_rect_get_item_shapefile(mr);
631 }
632
633 static struct map_methods map_methods_shapefile = {
634 projection_mg,
635 "iso8859-1",
636 map_destroy_shapefile,
637 map_rect_new_shapefile,
638 map_rect_destroy_shapefile,
639 map_rect_get_item_shapefile,
640 map_rect_get_item_byid_shapefile,
641 };
642
643 static struct map_priv *
644 map_new_shapefile(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
645 {
646 struct map_priv *m;
647 struct attr *data=attr_search(attrs, NULL, attr_data);
648 struct attr *charset=attr_search(attrs, NULL, attr_charset);
649 struct attr *projectionname=attr_search(attrs, NULL, attr_projectionname);
650 struct attr *flags=attr_search(attrs, NULL, attr_flags);
651 struct file_wordexp *wexp;
652 char *wdata;
653 char **wexp_data;
654 char *shapefile,*dbffile;
655 if (! data)
656 return NULL;
657 dbg(1,"map_new_shapefile %s\n", data->u.str);
658 wdata=g_strdup(data->u.str);
659 wexp=file_wordexp_new(wdata);
660 wexp_data=file_wordexp_get_array(wexp);
661 *meth=map_methods_shapefile;
662
663 m=g_new0(struct map_priv, 1);
664 m->filename=g_strdup(wexp_data[0]);
665 shapefile=g_strdup_printf("%s.shp", m->filename);
666 m->hSHP=SHPOpen(shapefile, "rb" );
667 SHPGetInfo( m->hSHP, &m->nEntities, &m->nShapeType, m->adfMinBound, m->adfMaxBound );
668 g_free(shapefile);
669 dbffile=g_strdup_printf("%s.dbf", m->filename);
670 m->hDBF=DBFOpen(dbffile, "rb");
671 m->nFields=DBFGetFieldCount(m->hDBF);
672 g_free(dbffile);
673 dbg(1,"map_new_shapefile %s %s\n", m->filename, wdata);
674 if (charset) {
675 m->charset=g_strdup(charset->u.str);
676 meth->charset=m->charset;
677 }
678 if (projectionname)
679 m->pro=projection_from_name(projectionname->u.str, &m->offset);
680 if (flags)
681 m->flags=flags->u.num;
682 file_wordexp_destroy(wexp);
683 return m;
684 }
685
686 void
687 plugin_init(void)
688 {
689 dbg(1,"shapefile: plugin_init\n");
690 plugin_register_map_type("shapefile", map_new_shapefile);
691 }
692
693 /************************************************************************/
694 /* VSI_SHP_Open() */
695 /************************************************************************/
696
697 static SAFile VSI_SHP_Open( const char *pszFilename, const char *pszAccess )
698
699 {
700 return (SAFile)fopen(pszFilename, pszAccess);
701 }
702
703 /************************************************************************/
704 /* VSI_SHP_Read() */
705 /************************************************************************/
706
707 static SAOffset VSI_SHP_Read( void *p, SAOffset size, SAOffset nmemb, SAFile file )
708
709 {
710 return fread(p, size, nmemb, (FILE *)file);
711 }
712
713 /************************************************************************/
714 /* VSI_SHP_Write() */
715 /************************************************************************/
716
717 static SAOffset VSI_SHP_Write( void *p, SAOffset size, SAOffset nmemb, SAFile file )
718
719 {
720 return fwrite(p, size, nmemb, (FILE *)file);
721 }
722
723 /************************************************************************/
724 /* VSI_SHP_Seek() */
725 /************************************************************************/
726
727 static SAOffset VSI_SHP_Seek( SAFile file, SAOffset offset, int whence )
728
729 {
730 return fseek((FILE *)file, offset, whence);
731 }
732
733 /************************************************************************/
734 /* VSI_SHP_Tell() */
735 /************************************************************************/
736
737 static SAOffset VSI_SHP_Tell( SAFile file )
738
739 {
740 return ftell((FILE *)file);
741 }
742
743
744 static int VSI_SHP_Flush( SAFile file )
745
746 {
747 return fflush((FILE *)file);
748 }
749
750 /************************************************************************/
751 /* VSI_SHP_Close() */
752 /************************************************************************/
753
754 static int VSI_SHP_Close( SAFile file )
755
756 {
757 return fclose((FILE *)file);
758 }
759
760 /************************************************************************/
761 /* SADError() */
762 /************************************************************************/
763
764 static void VSI_SHP_Error( const char *message )
765
766 {
767 dbg(0,"error:%s\n", message);
768 }
769
770 /************************************************************************/
771 /* VSI_SHP_Remove() */
772 /************************************************************************/
773
774 static int VSI_SHP_Remove( const char *pszFilename )
775
776 {
777 return unlink(pszFilename);
778 }
779
780 /************************************************************************/
781 /* SASetupDefaultHooks() */
782 /************************************************************************/
783
784 void SASetupDefaultHooks( SAHooks *psHooks )
785
786 {
787 psHooks->FOpen = VSI_SHP_Open;
788 psHooks->FRead = VSI_SHP_Read;
789 psHooks->FWrite = VSI_SHP_Write;
790 psHooks->FSeek = VSI_SHP_Seek;
791 psHooks->FTell = VSI_SHP_Tell;
792 psHooks->FFlush = VSI_SHP_Flush;
793 psHooks->FClose = VSI_SHP_Close;
794
795 psHooks->Remove = VSI_SHP_Remove;
796 psHooks->Atof = atof;
797
798 psHooks->Error = VSI_SHP_Error;
799 }
800
801

   
Visit the ZANavi Wiki