PostGIS  2.2.7dev-r@@SVN_REVISION@@
Datum LWGEOM_dump ( PG_FUNCTION_ARGS  )

Definition at line 57 of file lwgeom_dump.c.

References GEOMDUMPNODE_T::geom, LWCOLLECTION::geoms, GEOMDUMPNODE_T::idx, if(), LAST, lwalloc(), lwgeom_from_gserialized(), lwgeom_is_collection(), lwgeom_is_empty(), lwgeom_to_hexwkb(), LWCOLLECTION::ngeoms, POP, PUSH, GEOMDUMPSTATE::root, LWGEOM::srid, GEOMDUMPSTATE::stack, GEOMDUMPSTATE::stacklen, and WKB_EXTENDED.

58 {
59  GSERIALIZED *pglwgeom;
60  LWCOLLECTION *lwcoll;
61  LWGEOM *lwgeom;
62  FuncCallContext *funcctx;
63  GEOMDUMPSTATE *state;
64  GEOMDUMPNODE *node;
65  TupleDesc tupdesc;
66  HeapTuple tuple;
67  AttInMetadata *attinmeta;
68  MemoryContext oldcontext, newcontext;
69  Datum result;
70  char address[256];
71  char *ptr;
72  uint32 i;
73  char *values[2];
74 
75  if (SRF_IS_FIRSTCALL())
76  {
77  funcctx = SRF_FIRSTCALL_INIT();
78  newcontext = funcctx->multi_call_memory_ctx;
79 
80  oldcontext = MemoryContextSwitchTo(newcontext);
81 
82  pglwgeom = PG_GETARG_GSERIALIZED_P_COPY(0);
83  lwgeom = lwgeom_from_gserialized(pglwgeom);
84 
85  /* Create function state */
86  state = lwalloc(sizeof(GEOMDUMPSTATE));
87  state->root = lwgeom;
88  state->stacklen=0;
89 
90  if ( lwgeom_is_collection(lwgeom) )
91  {
92  /*
93  * Push a GEOMDUMPNODE on the state stack
94  */
95  node = lwalloc(sizeof(GEOMDUMPNODE));
96  node->idx=0;
97  node->geom = lwgeom;
98  PUSH(state, node);
99  }
100 
101  funcctx->user_fctx = state;
102 
103  /*
104  * Build a tuple description for an
105  * geometry_dump tuple
106  */
107  tupdesc = RelationNameGetTupleDesc("geometry_dump");
108 
109  /*
110  * generate attribute metadata needed later to produce
111  * tuples from raw C strings
112  */
113  attinmeta = TupleDescGetAttInMetadata(tupdesc);
114  funcctx->attinmeta = attinmeta;
115 
116  MemoryContextSwitchTo(oldcontext);
117  }
118 
119  /* stuff done on every call of the function */
120  funcctx = SRF_PERCALL_SETUP();
121  newcontext = funcctx->multi_call_memory_ctx;
122 
123  /* get state */
124  state = funcctx->user_fctx;
125 
126  /* Handled simple geometries */
127  if ( ! state->root ) SRF_RETURN_DONE(funcctx);
128  /* Return nothing for empties */
129  if ( lwgeom_is_empty(state->root) ) SRF_RETURN_DONE(funcctx);
130  if ( ! lwgeom_is_collection(state->root) )
131  {
132  values[0] = "{}";
133  values[1] = lwgeom_to_hexwkb(state->root, WKB_EXTENDED, 0);
134  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
135  result = HeapTupleGetDatum(tuple);
136 
137  state->root = NULL;
138  SRF_RETURN_NEXT(funcctx, result);
139  }
140 
141  while (1)
142  {
143  node = LAST(state);
144  lwcoll = (LWCOLLECTION*)node->geom;
145 
146  if ( node->idx < lwcoll->ngeoms )
147  {
148  lwgeom = lwcoll->geoms[node->idx];
149  if ( ! lwgeom_is_collection(lwgeom) )
150  {
151  /* write address of current geom */
152  ptr=address;
153  *ptr++='{';
154  for (i=0; i<state->stacklen; i++)
155  {
156  if ( i ) ptr += sprintf(ptr, ",");
157  ptr += sprintf(ptr, "%d", state->stack[i]->idx+1);
158  }
159  *ptr++='}';
160  *ptr='\0';
161 
162  break;
163  }
164 
165  /*
166  * It's a collection, increment index
167  * of current node, push a new one on the
168  * stack
169  */
170 
171  oldcontext = MemoryContextSwitchTo(newcontext);
172 
173  node = lwalloc(sizeof(GEOMDUMPNODE));
174  node->idx=0;
175  node->geom = lwgeom;
176  PUSH(state, node);
177 
178  MemoryContextSwitchTo(oldcontext);
179 
180  continue;
181  }
182 
183  if ( ! POP(state) ) SRF_RETURN_DONE(funcctx);
184  LAST(state)->idx++;
185  }
186 
187  lwgeom->srid = state->root->srid;
188 
189  values[0] = address;
190  values[1] = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, 0);
191  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
192  result = TupleGetDatum(funcctx->slot, tuple);
193  node->idx++;
194  SRF_RETURN_NEXT(funcctx, result);
195 }
char * lwgeom_to_hexwkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Definition: lwout_wkb.c:834
#define POP(x)
Definition: lwgeom_dump.c:53
#define PUSH(x, y)
Definition: lwgeom_dump.c:51
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:991
LWGEOM * root
Definition: lwgeom_dump.c:47
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int32_t srid
Definition: liblwgeom.h:383
LWGEOM ** geoms
Definition: liblwgeom.h:493
GEOMDUMPNODE * stack[MAXDEPTH]
Definition: lwgeom_dump.c:46
#define LAST(x)
Definition: lwgeom_dump.c:52
#define WKB_EXTENDED
Definition: liblwgeom.h:1932
LWGEOM * geom
Definition: lwgeom_dump.c:38
void * lwalloc(size_t size)
Definition: lwutil.c:199
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1297
if(!(yy_init))
Definition: lwin_wkt_lex.c:863

Here is the call graph for this function: