Jelajahi Sumber

vlib: add V2__delete_line_topo_nat()
update V2__add_line_topo_nat()
add extra checks (invalid line id) + update doxygen (note required build level)
various minor issue


git-svn-id: https://svn.osgeo.org/grass/grass/trunk@55582 15284696-431f-4ddb-bdfa-cd5b030d7da7

Martin Landa 12 tahun lalu
induk
melakukan
955ec9ab4c

+ 12 - 21
lib/vector/Vlib/bridges.c

@@ -28,9 +28,8 @@ static int cmp_int(const void *a, const void *b)
     return (*ai < *bi ? -1 : (*ai > *bi));
 }
 
-static void
-remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err, 
-               int *lrm, int *brm);
+static void remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err, 
+                           int *lrm, int *brm);
 
 /*!
    \brief Remove bridges from vector map.
@@ -45,12 +44,9 @@ remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err,
    \param Err vector map where deleted bridges are written or NULL
    \param lines_removed number of lines removed
    \param bridges_removed Err number of bridges removed
-
-   \return
- */
-void
-Vect_remove_bridges(struct Map_info *Map, struct Map_info *Err,
-                    int *lines_removed, int *bridges_removed)
+*/
+void Vect_remove_bridges(struct Map_info *Map, struct Map_info *Err,
+                         int *lines_removed, int *bridges_removed)
 {
     remove_bridges(Map, 0, Err, lines_removed, bridges_removed);
 }
@@ -69,12 +65,8 @@ Vect_remove_bridges(struct Map_info *Map, struct Map_info *Err,
    \param Err vector map where changed bridges are written or NULL
    \param lines_changed number of lines changed
    \param bridges_changed Err number of bridges changed
-
-   \return
- */
-
-void
-Vect_chtype_bridges(struct Map_info *Map, struct Map_info *Err,
+*/
+void Vect_chtype_bridges(struct Map_info *Map, struct Map_info *Err,
                     int *lines_changed, int *bridges_changed)
 {
     remove_bridges(Map, 1, Err, lines_changed, bridges_changed);
@@ -93,11 +85,10 @@ Vect_chtype_bridges(struct Map_info *Map, struct Map_info *Err,
 
    List of all lines in chain is created during the cycle.
  */
-void
-remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err,
-               int *lrm, int *brm)
+void remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err,
+                    int *lrm, int *brm)
 {
-    int i, type, nlines, line, *bline;
+    int type, nlines, line, *bline;
     int left, right, node1, node2, current_line, next_line, abs_line;
     int bridges_removed = 0;	/* number of removed bridges */
     int lines_removed = 0;	/* number of lines removed */
@@ -219,6 +210,6 @@ remove_bridges(struct Map_info *Map, int chtype, struct Map_info *Err,
     if (brm)
 	*brm = bridges_removed;
 
-    G_verbose_message("Removed lines: %d", lines_removed);
-    G_verbose_message("Removed bridges: %d", bridges_removed);
+    G_verbose_message(_("Removed lines: %d"), lines_removed);
+    G_verbose_message(_("Removed bridges: %d"), bridges_removed);
 }

+ 9 - 3
lib/vector/Vlib/local_proto.h

@@ -3,9 +3,8 @@
 
 #include <grass/vector.h>
 
-void V2__add_line_to_topo_nat(struct Map_info *, int ,
-                              const struct line_pnts *, const struct line_cats *,
-                              int (*external_routine) (const struct Map_info *, int));
+/* Internal vector library subroutines which are not part of public
+   API*/
 
 /* map.c */
 int Vect__delete(const char *, int);
@@ -16,4 +15,11 @@ int Vect__open_old(struct Map_info *, const char *, const char *,
 char *Vect__get_path(const struct Map_info *);
 char *Vect__get_element_path(const struct Map_info *, const char *);
 
+/* write_nat.c */
+int V2__add_line_to_topo_nat(struct Map_info *, off_t, int,
+                             const struct line_pnts *, const struct line_cats *, int,
+                             int (*external_routine) (const struct Map_info *, int));
+int V2__delete_line_from_topo_nat(struct Map_info *, int, int,
+                                  const struct line_pnts *, const struct line_cats *);
+
 #endif /* PG_LOCAL_PROTO_H__ */

+ 2 - 1
lib/vector/Vlib/open.c

@@ -782,6 +782,8 @@ int open_new(struct Map_info *Map, const char *name, int with_z, int is_tmp)
     /* set 2D/3D */
     Map->plus.spidx_with_z = Map->plus.with_z = Map->head.with_z = (with_z != 0);
 
+    Map->level = LEVEL_1;
+    
     if ((*Open_new_array[Map->format][1]) (Map, name, with_z) < 0) {
         if (getenv("GRASS_VECTOR_PGFILE") == NULL)  /* GRASS_VECTOR_PGFILE defined by v.out.postgis */
             Vect_delete(name); /* clean up */
@@ -798,7 +800,6 @@ int open_new(struct Map_info *Map, const char *name, int with_z, int is_tmp)
     Vect_open_sidx(Map, 2);
 
     Map->open = VECT_OPEN_CODE;
-    Map->level = 1;
     Map->head_only = FALSE;
     Map->support_updated = FALSE;
     Map->plus.built = GV_BUILD_NONE;

+ 73 - 42
lib/vector/Vlib/read.c

@@ -5,7 +5,7 @@
 
    Higher level functions for reading/writing/manipulating vectors.
 
-   (C) 2001-2009, 2011 by the GRASS Development Team
+   (C) 2001-2009, 2011-2013 by the GRASS Development Team
 
    This program is free software under the GNU General Public License
    (>=v2). Read the file COPYING that comes with GRASS for details.
@@ -83,13 +83,16 @@ static int (*Read_line_array[]) () = {
   \param Map pointer to Map_info struct
 
   \return feature id
+  \return -1 on error
 */
 int Vect_get_next_line_id(const struct Map_info *Map)
 {
     G_debug(3, "Vect_get_next_line()");
 
-    if (!VECT_OPEN(Map))
-	G_fatal_error(_("Vector map is not open for reading"));
+    if (!VECT_OPEN(Map)) {
+	G_warning(_("Vector map is not open for reading"));
+        return -1;
+    }
     
     return Map->next_line - 1;
 }
@@ -99,17 +102,17 @@ int Vect_get_next_line_id(const struct Map_info *Map)
 
    This function implements sequential access, constraints are
    reflected, see Vect_set_constraint_region(),
-   Vect_set_constraint_type(), or Vect_set_constraint_field().
+   Vect_set_constraint_type(), or Vect_set_constraint_field() for
+   details.
      
-   Use Vect_rewind() to reset reading.
+   Use Vect_rewind() to reset reading. Topological level is not
+   required.
 
-   G_fatal_error() is called on failure.
+   A warning is printed on failure.
    
    \param Map pointer Map_info struct
-   \param[out] line_p feature geometry
-   (pointer to line_pnts struct)
-   \param[out] line_c feature categories
-   (pointer to line_cats struct)
+   \param[out] line_p feature geometry (pointer to line_pnts struct)
+   \param[out] line_c feature categories (pointer to line_cats struct)
 
    \return feature type (GV_POINT, GV_LINE, ...)
    \return -1 on error
@@ -122,32 +125,32 @@ int Vect_read_next_line(const struct Map_info *Map,
     
     G_debug(3, "Vect_read_next_line(): next_line = %d", Map->next_line);
 
-    if (!VECT_OPEN(Map))
-	G_fatal_error(_("Vector map is not open for reading"));
+    if (!VECT_OPEN(Map)) {
+	G_warning(_("Vector map is not open for reading"));
+        return -1;
+    }
     
     ret = (*Read_next_line_array[Map->format][Map->level]) (Map, line_p,
 							    line_c);
-    /* 
     if (ret == -1)
-	G_fatal_error(_("Unable to read feature %d vector map <%s>"),
-		      Map->next_line, Vect_get_full_name(Map));
-    */
+        G_warning(_("Unable to read feature %d from vector map <%s>"),
+                  Map->next_line, Vect_get_full_name(Map));
+    
     return ret;
 }
 
 /*!
-   \brief Read vector feature
+   \brief Read vector feature (topological level required)
 
-   This function implements random access. Note that constraits are
-   ignored!
+   This function implements random access. Constraits are ignored.
 
-   G_fatal_error() is called on failure.
+   Note: Topology must be built at level >= GV_BUILD_BASE
+
+   A warning is printed on failure.
    
    \param Map pointer to vector map
-   \param[out] line_p feature geometry
-   (pointer to line_pnts struct)
-   \param[out] line_c feature categories
-   (pointer to line_cats struct)
+   \param[out] line_p feature geometry (pointer to line_pnts struct)
+   \param[out] line_c feature categories (pointer to line_cats struct)
    \param line feature id (starts at 1)
    
    \return feature type
@@ -161,35 +164,43 @@ int Vect_read_line(const struct Map_info *Map,
     
     G_debug(3, "Vect_read_line(): line = %d", line);
 
-    if (!VECT_OPEN(Map))
-	G_fatal_error(_("Vector map is not open for reading"));
-
-    if (line < 1 || line > Map->plus.n_lines)
-	G_fatal_error(_("Requested feature id %d is not reasonable"
-			"(max features in vector map <%s>: %d)"),
-		      line, Vect_get_full_name(Map), Map->plus.n_lines);
-
+    if (!VECT_OPEN(Map)) {
+	G_warning(_("Vector map is not open for reading"));
+        return -1;
+    }
+    
+    if (line < 1 || line > Map->plus.n_lines) {
+        G_warning(_("Attempt to access feature with invalid id (%d)"), line);
+        return -1;
+    }
+    
     ret = (*Read_line_array[Map->format]) (Map, line_p, line_c, line);
 
-    /*
     if (ret == -1)
-	G_fatal_error(_("Unable to read feature %d from vector map <%s>"),
-		      line, Vect_get_full_name(Map));
-    */
+	G_warning(_("Unable to read feature %d from vector map <%s>"),
+                  line, Vect_get_full_name(Map));
+    
     return ret;
 }
 
 /*!
-  \brief Check if feature is alive or dead (level 2 required)
+  \brief Check if feature is alive or dead (topological level required)
   
+  Note: Topology must be built at level >= GV_BUILD_BASE
+
   \param Map pointer to Map_info structure
   \param line feature id
   
   \return 1 feature alive
   \return 0 feature is dead
+  \return -1 on error
  */
 int Vect_line_alive(const struct Map_info *Map, int line)
 {
+    if (line < 1 || line > Map->plus.n_lines) {
+        return -1;
+    }
+
     if (Map->plus.Line[line] != NULL)
 	return 1;
     
@@ -197,8 +208,10 @@ int Vect_line_alive(const struct Map_info *Map, int line)
 }
 
 /*!
-  \brief Check if node is alive or dead (level 2 required)
+  \brief Check if node is alive or dead (topological level required)
   
+  Note: Topology must be built at level >= GV_BUILD_BASE
+
   \param Map pointer to Map_info structure
   \param node node id
   
@@ -207,6 +220,10 @@ int Vect_line_alive(const struct Map_info *Map, int line)
  */
 int Vect_node_alive(const struct Map_info *Map, int node)
 {
+    if (node < 1 || node > Map->plus.n_nodes) {
+        return -1;
+    }
+
     if (Map->plus.Node[node] != NULL)
 	return 1;
 
@@ -214,16 +231,22 @@ int Vect_node_alive(const struct Map_info *Map, int node)
 }
 
 /*!
-  \brief Check if area is alive or dead (level 2 required)
+  \brief Check if area is alive or dead (topological level required)
   
+  Note: Topology must be built at level >= GV_BUILD_AREAS
+
   \param Map pointer to Map_info structure
   \param area area id
   
   \return 1 area alive
   \return 0 area is dead
+  \return -1 on error
 */
 int Vect_area_alive(const struct Map_info *Map, int area)
 {
+    if (area < 1 || area > Map->plus.n_areas)
+        return -1;
+    
     if (Map->plus.Area[area] != NULL)
 	return 1;
 
@@ -231,8 +254,10 @@ int Vect_area_alive(const struct Map_info *Map, int area)
 }
 
 /*!
-  \brief Check if isle is alive or dead (level 2 required)
+  \brief Check if isle is alive or dead (topological level required)
 
+  Note: Topology must be built at level >= GV_BUILD_AREAS
+  
   \param Map pointer to Map_info structure
   \param isle isle id
   
@@ -241,6 +266,9 @@ int Vect_area_alive(const struct Map_info *Map, int area)
 */
 int Vect_isle_alive(const struct Map_info *Map, int isle)
 {
+    if (isle < 1 || isle > Map->plus.n_isles)
+        return -1;
+
     if (Map->plus.Isle[isle] != NULL)
 	return 1;
 
@@ -248,7 +276,9 @@ int Vect_isle_alive(const struct Map_info *Map, int isle)
 }
 
 /*!
-  \brief Get feature offset
+  \brief Get feature offset (topological level required)
+  
+  Note: Topology must be built at level >= GV_BUILD_BASE
   
   Used for Vect_restore_line().
   
@@ -260,8 +290,9 @@ int Vect_isle_alive(const struct Map_info *Map, int isle)
 */
 off_t Vect_get_line_offset(const struct Map_info *Map, int line)
 {
-    if (line < 1 || line > Map->plus.n_lines)
+    if (line < 1 || line > Map->plus.n_lines) {
 	return -1;
+    }
     
     if (Map->plus.Line[line] != NULL) {
 	return Map->plus.Line[line]->offset;

+ 10 - 6
lib/vector/Vlib/read_nat.c

@@ -122,11 +122,11 @@ int V1_read_next_line_nat(struct Map_info *Map,
   This function implements random access for native format,
   constraints are ignored!
   
+  Note: Topology must be built at level >= GV_BUILD_BASE
+  
   \param Map pointer to Map_info struct 
-  \param[out] Points container used to store line points within
-  (pointer to line_pnts struct)
-  \param[out] Cats container used to store line categories within
-  (pointer to line_cats struct)
+  \param[out] Points container used to store line points within (pointer to line_pnts struct)
+  \param[out] Cats container used to store line categories within (pointer to line_cats struct)
   \param line feature id to read (starts at 1)
   
   \return feature type (GV_POINT, GV_LINE, ...)
@@ -140,10 +140,14 @@ int V2_read_line_nat(struct Map_info *Map,
 
     G_debug(3, "V2_read_line_nat(): line = %d", line);
 
+    if (line < 1 || line > Map->plus.n_lines) {
+        G_warning(_("Attempt to access feature with invalid id (%d)"), line);
+        return -1;
+    }
+    
     Line = Map->plus.Line[line];
-
     if (Line == NULL) {
-	G_warning(_("Attempt to read dead feature %d"), line);
+	G_warning(_("Attempt to access dead feature %d"), line);
 	return -1;
     }
 

+ 13 - 4
lib/vector/Vlib/read_sfa.c

@@ -24,6 +24,8 @@
  
   This function implements random access on level 2.
   
+  Note: Topology must be built at level >= GV_BUILD_BASE
+  
   \param Map pointer to Map_info structure
   \param[out] line_p container used to store line points within
   (pointer to line_pnts struct)
@@ -44,9 +46,14 @@ int V2_read_line_sfa(struct Map_info *Map, struct line_pnts *line_p,
     
     G_debug(4, "V2_read_line_sfa() line = %d", line);
     
+    if (line < 1 || line > Map->plus.n_lines) {
+        G_warning(_("Attempt to access feature with invalid id (%d)"), line);
+        return -1;
+    }
+
     Line = Map->plus.Line[line];
     if (Line == NULL) {
-        G_warning(_("Attempt to read dead feature %d"), line);
+        G_warning(_("Attempt to access dead feature %d"), line);
         return -1;
     }
     
@@ -106,9 +113,11 @@ int V2_read_line_sfa(struct Map_info *Map, struct line_pnts *line_p,
     else
         type = V1_read_line_ogr(Map, line_p, line_c, Line->offset);
 
-    if (type != Line->type)
-        G_fatal_error(_("Unexpected feature type (%d) - should be (%d)"),
-                      type, Line->type);
+    if (type != Line->type) {
+        G_warning(_("Unexpected feature type (%d) - should be (%d)"),
+                  type, Line->type);
+        return -1;
+    }
 
     return type;
 #else

+ 90 - 72
lib/vector/Vlib/write.c

@@ -5,20 +5,19 @@
 
    Higher level functions for reading/writing/manipulating vectors.
 
-   Operations:
-    - Write new feature
-    - Rewrite feature
-    - Delete feature
+   Supported operations:
+    - Write a new feature
+    - Rewrite existing feature
+    - Delete existing feature
     - Restore deleted feature
 
-   (C) 2001-2010, 2012 by the GRASS Development Team
+   (C) 2001-2010, 2012-2013 by the GRASS Development Team
 
    This program is free software under the GNU General Public License
    (>=v2). Read the file COPYING that comes with GRASS for details.
 
    \author Radim Blazek
-   \author Updated by Martin Landa <landa.martin gmail.com>
-   (restore lines, OGR & PostGIS support)
+   \author Updated by Martin Landa <landa.martin gmail.com> (restore lines, OGR & PostGIS support)
  */
 
 #include <sys/types.h>
@@ -104,7 +103,7 @@ static off_t (*Vect_rewrite_line_array[][3]) () = {
 #endif
 #ifdef HAVE_POSTGRES
     , {
-	rewrite_dummy, V1_rewrite_line_pg, V2_rewrite_line_sfa}
+	rewrite_dummy, V1_rewrite_line_pg, V2_rewrite_line_pg}
 #else
     , {
 	rewrite_dummy, format_l, format_l}
@@ -127,7 +126,7 @@ static int (*Vect_delete_line_array[][3]) () = {
 #endif
 #ifdef HAVE_POSTGRES
     , {
-	delete_dummy, V1_delete_line_pg, V2_delete_line_sfa}
+	delete_dummy, V1_delete_line_pg, V2_delete_line_pg}
 #else
     , {
 	delete_dummy, format, format}
@@ -157,20 +156,22 @@ static int (*Vect_restore_line_array[][3]) () = {
 #endif
 };
 
+static int check_map(const struct Map_info *);
+
 /*!
-   \brief Writes new feature
+   \brief Writes a new feature
 
    New feature is written to the end of file (in the case of native
-   format). Vector map topology is not required.
+   format). Topological level is not required.
 
-   Calls G_fatal_error() when vector map is not opened.
+   A warning is printed on error.
    
    \param Map pointer to Map_info structure
    \param type feature type (see dig_defines.h for supported types)
-   \param points ointer to line_pnts structure (feature geometry)
+   \param points pointer to line_pnts structure (feature geometry)
    \param cats pointer to line_cats structure (feature categories)
 
-   \return new feature id (on level 2)
+   \return new feature id (on level 2) (or 0 when build level < GV_BUILD_BASE)
    \return offset into file where the feature starts (on level 1)
    \return -1 on error
  */
@@ -182,44 +183,42 @@ off_t Vect_write_line(struct Map_info *Map, int type,
     G_debug(3, "Vect_write_line(): name = %s, format = %d, level = %d",
 	    Map->name, Map->format, Map->level);
 
-    if (!VECT_OPEN(Map))
-	G_fatal_error(_("Unable to write feature, vector map is not opened"));
-
+    if (!VECT_OPEN(Map)) {
+	G_warning(_("Vector map <%s> is not opened"), Vect_get_name(Map));
+        return -1;
+    }
+    
     if (!(Map->plus.update_cidx)) {
-	Map->plus.cidx_up_to_date = FALSE;
+	Map->plus.cidx_up_to_date = FALSE; /* category index will be outdated */
     }
 
     offset = 
 	(*Vect_write_line_array[Map->format][Map->level]) (Map, type, points,
 							   cats);
     
-    /*
-    if (offset == -1)
-	G_fatal_error(_("Unable to write feature (negative offset)"));
-    */
+    if (offset < 0)
+	G_warning(_("Unable to write feature in vector map <%s>"), Vect_get_name(Map));
     
-    /* note: returns new feature id on level 2 and file offset on
-       level 1 */
     return offset;
 }
 
 /*!
-   \brief Rewrites feature info at the given offset.
+   \brief Rewrites existing feature (topological level required)
 
-   Vector map must be opened with full topology (level 2).
+   Note: Topology must be built at level >= GV_BUILD_BASE
+   
+   A warning is printed on error.
 
    The number of points or cats or type may change. If necessary, the
    old feature is deleted and new is written.
 
-   This function calls G_fatal_error() on error.
-
    \param Map pointer to Map_info structure
    \param line feature id
    \param type feature type (GV_POINT, GV_LINE, ...)
    \param points feature geometry
    \param cats feature categories
 
-   \return feature offset
+   \return new feature offset
    \return -1 on error
  */
 off_t Vect_rewrite_line(struct Map_info *Map, int line, int type,
@@ -227,32 +226,38 @@ off_t Vect_rewrite_line(struct Map_info *Map, int line, int type,
 {
     off_t ret, offset;
     
-    if (!VECT_OPEN(Map))
-	G_fatal_error(_("Unable to rewrite feature, vector map is not opened"));
+    if (!check_map(Map))
+        return -1;
 
+    if (line < 1 || line > Map->plus.n_lines) {
+        G_warning(_("Attempt to access feature with invalid id (%d)"), line);
+        return -1;
+    }
+    
     if (!(Map->plus.update_cidx)) {
-	Map->plus.cidx_up_to_date = FALSE;
+	Map->plus.cidx_up_to_date = FALSE; /* category index will be outdated */
     }
 
     offset = Map->plus.Line[line]->offset;
-    G_debug(3, "Vect_rewrite_line(): name = %s, line = %d offset = %lu",
+    
+    G_debug(3, "Vect_rewrite_line(): name = %s, line = %d, offset = %lu",
 	    Map->name, line, offset);
+    
     ret = (*Vect_rewrite_line_array[Map->format][Map->level]) (Map, line, type,
 							       offset,
 							       points, cats);
-    /*
     if (ret == -1)
-	G_fatal_error(_("Unable to rewrite feature %d"), line);
-    */
+        G_warning(_("Unable to rewrite feature %d in vector map <%s>"), line, Vect_get_name(Map));
+
     return ret;
 }
 
 /*!
-   \brief Delete feature
-
-   Vector map must be opened with full topology (level 2).
+   \brief Delete existing feature (topological level required)
 
-   This function calls G_fatal_error() on error.
+   Note: Topology must be built at level >= GV_BUILD_BASE
+   
+   A warning is printed on error.
 
    \param Map pointer to Map_info structure
    \param line feature id
@@ -266,41 +271,37 @@ int Vect_delete_line(struct Map_info *Map, int line)
 
     G_debug(3, "Vect_delete_line(): name = %s, line = %d", Map->name, line);
 
-    if (Map->level < 2) {
-	G_fatal_error(_("Unable to delete feature %d, "
-			"vector map <%s> is not opened on topology level"),
-		      line, Map->name);
-    }
-
-    if (Map->mode != GV_MODE_RW && Map->mode != GV_MODE_WRITE) {
-	G_fatal_error(_("Unable to delete feature %d, "
-			"vector map <%s> is not opened in 'write' mode"),
-		      line, Map->name);
+    if (!check_map(Map))
+        return -1;
+    
+    if (line < 1 || line > Map->plus.n_lines) {
+        G_warning(_("Attempt to access feature with invalid id (%d)"), line);
+        return -1;
     }
 
     if (!(Map->plus.update_cidx)) {
-	Map->plus.cidx_up_to_date = FALSE;
+	Map->plus.cidx_up_to_date = FALSE; /* category index will be outdated */
     }
 
     ret = (*Vect_delete_line_array[Map->format][Map->level]) (Map, line);
 
-    /*
     if (ret == -1)
-	G_fatal_error(_("Unable to delete feature id %d from vector map <%s>"),
-		      line, Vect_get_full_name(Map));
-    */
+	G_warning(_("Unable to delete feature %d from vector map <%s>"),
+                  line, Vect_get_name(Map));
+
     return ret;
 }
 
 /*!
-   \brief Restore previously deleted feature
-
-   Vector map must be opened with full topology (level 2).
+   \brief Restore previously deleted feature (topological level required)
 
-   This function calls G_fatal_error() on error.
+   Note: Topology must be built at level >= GV_BUILD_BASE
+   
+   A warning is printed on error.
 
    \param Map pointer to Map_info structure
    \param line feature id to be restored
+   \param offset feature offset
 
    \return 0 on success
    \return -1 on error
@@ -311,16 +312,12 @@ int Vect_restore_line(struct Map_info *Map, int line, off_t offset)
 
     G_debug(3, "Vect_restore_line(): name = %s, line = %d", Map->name, line);
 
-    if (Map->level < 2) {
-	G_fatal_error(_("Unable to restore feature %d, "
-			"vector map <%s> is not opened on topology level"),
-		      line, Map->name);
-    }
+    if (!check_map(Map))
+        return -1;
 
-    if (Map->mode != GV_MODE_RW && Map->mode != GV_MODE_WRITE) {
-	G_fatal_error(_("Unable to restore feature %d, "
-			"vector map <%s> is not opened in 'write' mode"),
-		      line, Map->name);
+    if (line < 1 || line > Map->plus.n_lines) {
+        G_warning(_("Attempt to access feature with invalid id (%d)"), line);
+        return -1;
     }
 
     if (!(Map->plus.update_cidx)) {
@@ -329,10 +326,31 @@ int Vect_restore_line(struct Map_info *Map, int line, off_t offset)
 
     ret = (*Vect_restore_line_array[Map->format][Map->level]) (Map, line, offset);
 
-    /*
     if (ret == -1)
-	G_fatal_error(_("Unable to restore feature %d from vector map <%s>"),
-		      line, Map->name);
-    */
+	G_warning(_("Unable to restore feature %d in vector map <%s>"),
+                  line, Vect_get_name(Map));
+
     return ret;
 }
+
+int check_map(const struct Map_info *Map)
+{
+    if (!VECT_OPEN(Map)) {
+	G_warning(_("Vector map <%s> is not opened"), Vect_get_name(Map));
+        return 0;
+    }
+    
+    if (Map->level < 2) {
+	G_warning(_("Vector map <%s> is not opened on topology level"),
+                  Vect_get_name(Map));
+        return 0;
+    }
+
+    if (Map->mode != GV_MODE_RW && Map->mode != GV_MODE_WRITE) {
+	G_warning(_("Vector map <%s> is not opened in write mode"),
+                  Vect_get_name(Map));
+        return 0;
+    }
+    
+    return 1;
+}

File diff ditekan karena terlalu besar
+ 617 - 581
lib/vector/Vlib/write_nat.c


+ 21 - 4
lib/vector/Vlib/write_sfa.c

@@ -126,7 +126,9 @@ off_t V2_write_line_sfa(struct Map_info *Map, int type,
 /*!
   \brief Rewrites feature at the given offset on level 2 (OGR/PostGIS
   interface, pseudo-topological level)
-  
+
+  Note: Topology must be built at level >= GV_BUILD_BASE
+
   \param Map pointer to Map_info structure
   \param line feature id to be rewritten
   \param type feature type (see V1_write_line_ogr() for supported types)
@@ -143,13 +145,19 @@ off_t V2_rewrite_line_sfa(struct Map_info *Map, int line, int type, off_t offset
     G_debug(3, "V2_rewrite_line_sfa(): line=%d type=%d offset=%lu",
 	    line, type, offset);
 
+    if (line < 1 || line > Map->plus.n_lines) {
+        G_warning(_("Attempt to access feature with invalid id (%d)"), line);
+        return -1;
+    }
+
 #if defined HAVE_OGR || defined HAVE_POSTGRES
     if (type != V2_read_line_sfa(Map, NULL, NULL, line)) {
 	G_warning(_("Unable to rewrite feature (incompatible feature types)"));
 	return -1;
     }
 
-    V2_delete_line_sfa(Map, line);
+    if (V2_delete_line_sfa(Map, line) != 0)
+        return -1;
 
     return V2_write_line_sfa(Map, type, points, cats);
 #else
@@ -160,6 +168,8 @@ off_t V2_rewrite_line_sfa(struct Map_info *Map, int line, int type, off_t offset
 
 /*!
   \brief Deletes feature on level 2 (OGR/PostGIS interface)
+
+  Note: Topology must be built at level >= GV_BUILD_BASE
   
   \todo Update fidx
   
@@ -178,12 +188,17 @@ int V2_delete_line_sfa(struct Map_info *Map, int line)
     static struct line_cats *Cats = NULL;
     static struct line_pnts *Points = NULL;
 
-    G_debug(3, "V2_delete_line_sfa(), line = %d", line);
+    G_debug(3, "V2_delete_line_sfa(): line = %d", line);
 
     type = first = 0;
     Line = NULL;
     plus = &(Map->plus);
 
+    if (line < 1 || line > Map->plus.n_lines) {
+        G_warning(_("Attempt to access feature with invalid id (%d)"), line);
+        return -1;
+    }
+
     if (plus->built >= GV_BUILD_BASE) {
 	Line = Map->plus.Line[line];
 
@@ -200,7 +215,9 @@ int V2_delete_line_sfa(struct Map_info *Map, int line)
     }
 
     type = V2_read_line_sfa(Map, Points, Cats, line);
-
+    if (type < 0)
+        return -1;
+    
     /* Update category index */
     if (plus->update_cidx) {
       for (i = 0; i < Cats->n_cats; i++) {