Skip to content

Commit 9e7553e

Browse files
authored
Merge pull request #131 from paulmach/pm/missing-parens
encoding/wkt: better handling/validation of missing parens
2 parents f55e555 + 84be936 commit 9e7553e

File tree

2 files changed

+198
-79
lines changed

2 files changed

+198
-79
lines changed

encoding/wkt/unmarshal.go

Lines changed: 139 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ var (
2020
// ErrUnsupportedGeometry is returned when geometry type is not supported by this lib.
2121
ErrUnsupportedGeometry = errors.New("wkt: unsupported geometry")
2222

23-
doubleParen = regexp.MustCompile(`\)[\s|\t]*\)[\s|\t]*,[\s|\t]*\([\s|\t]*\(`)
24-
singleParen = regexp.MustCompile(`\)[\s|\t]*,[\s|\t]*\(`)
25-
noParen = regexp.MustCompile(`[\s|\t]*,[\s|\t]*`)
23+
doubleParen = regexp.MustCompile(`\)[\s|\t]*\)([\s|\t]*,[\s|\t]*)\([\s|\t]*\(`)
24+
singleParen = regexp.MustCompile(`\)([\s|\t]*,[\s|\t]*)\(`)
25+
noParen = regexp.MustCompile(`([\s|\t]*,[\s|\t]*)`)
2626
)
2727

2828
// UnmarshalPoint returns the point represented by the wkt string.
@@ -125,18 +125,24 @@ func UnmarshalCollection(s string) (p orb.Collection, err error) {
125125
}
126126

127127
// trimSpaceBrackets trim space and brackets
128-
func trimSpaceBrackets(s string) string {
128+
func trimSpaceBrackets(s string) (string, error) {
129129
s = strings.Trim(s, " ")
130130
if len(s) == 0 {
131-
return ""
131+
return "", nil
132132
}
133+
133134
if s[0] == '(' {
134135
s = s[1:]
136+
} else {
137+
return "", ErrNotWKT
135138
}
139+
136140
if s[len(s)-1] == ')' {
137141
s = s[:len(s)-1]
142+
} else {
143+
return "", ErrNotWKT
138144
}
139-
return strings.Trim(s, " ")
145+
return strings.Trim(s, " "), nil
140146
}
141147

142148
// parsePoint pase point by (x y)
@@ -193,134 +199,199 @@ func Unmarshal(s string) (geom orb.Geometry, err error) {
193199
if s == "GEOMETRYCOLLECTION EMPTY" {
194200
return orb.Collection{}, nil
195201
}
196-
s = strings.Replace(s, "GEOMETRYCOLLECTION", "", -1)
202+
203+
s = strings.ReplaceAll(s, "GEOMETRYCOLLECTION", "")
197204
if len(s) == 0 {
198205
return nil, ErrNotWKT
199206
}
200-
c := orb.Collection{}
201-
ms := splitGeometryCollection(s)
202-
if len(ms) == 0 {
207+
208+
tc := orb.Collection{}
209+
geometries := splitGeometryCollection(s)
210+
if len(geometries) == 0 {
203211
return nil, err
204212
}
205-
for _, v := range ms {
206-
if len(v) == 0 {
213+
214+
for _, g := range geometries {
215+
if len(g) == 0 {
207216
continue
208217
}
209-
g, err := Unmarshal(v)
218+
219+
tg, err := Unmarshal(g)
210220
if err != nil {
211221
return nil, err
212222
}
213-
c = append(c, g)
223+
224+
tc = append(tc, tg)
214225
}
215-
geom = c
226+
227+
geom = tc
216228

217229
case strings.Contains(s, "MULTIPOINT"):
218230
if s == "MULTIPOINT EMPTY" {
219231
return orb.MultiPoint{}, nil
220232
}
221-
s = strings.Replace(s, "MULTIPOINT", "", -1)
222-
s = trimSpaceBrackets(s)
233+
234+
s, err := trimSpaceBrackets(strings.ReplaceAll(s, "MULTIPOINT", ""))
235+
if err != nil {
236+
return nil, err
237+
}
238+
223239
ps := splitByRegexp(s, noParen)
224-
mp := orb.MultiPoint{}
240+
tmp := orb.MultiPoint{}
225241
for _, p := range ps {
226-
tp, err := parsePoint(trimSpaceBrackets(p))
242+
p, err := trimSpaceBrackets(p)
227243
if err != nil {
228244
return nil, err
229245
}
230-
mp = append(mp, tp)
246+
247+
tp, err := parsePoint(p)
248+
if err != nil {
249+
return nil, err
250+
}
251+
252+
tmp = append(tmp, tp)
231253
}
232-
geom = mp
254+
255+
geom = tmp
233256

234257
case strings.Contains(s, "POINT"):
235-
s = strings.Replace(s, "POINT", "", -1)
236-
tp, err := parsePoint(trimSpaceBrackets(s))
258+
s, err := trimSpaceBrackets(strings.ReplaceAll(s, "POINT", ""))
259+
if err != nil {
260+
return nil, err
261+
}
262+
263+
tp, err := parsePoint(s)
237264
if err != nil {
238265
return nil, err
239266
}
267+
240268
geom = tp
241269

242270
case strings.Contains(s, "MULTILINESTRING"):
243271
if s == "MULTILINESTRING EMPTY" {
244272
return orb.MultiLineString{}, nil
245273
}
246-
s = strings.Replace(s, "MULTILINESTRING", "", -1)
247-
ml := orb.MultiLineString{}
248-
for _, l := range splitByRegexp(trimSpaceBrackets(s), singleParen) {
249-
tl := orb.LineString{}
250-
for _, p := range splitByRegexp(trimSpaceBrackets(l), noParen) {
251-
tp, err := parsePoint(trimSpaceBrackets(p))
274+
275+
s, err := trimSpaceBrackets(strings.ReplaceAll(s, "MULTILINESTRING", ""))
276+
if err != nil {
277+
return nil, err
278+
}
279+
280+
tmls := orb.MultiLineString{}
281+
for _, ls := range splitByRegexp(s, singleParen) {
282+
ls, err := trimSpaceBrackets(ls)
283+
if err != nil {
284+
return nil, err
285+
}
286+
287+
tls := orb.LineString{}
288+
for _, p := range splitByRegexp(ls, noParen) {
289+
tp, err := parsePoint(p)
252290
if err != nil {
253291
return nil, err
254292
}
255-
tl = append(tl, tp)
293+
tls = append(tls, tp)
256294
}
257-
ml = append(ml, tl)
295+
tmls = append(tmls, tls)
258296
}
259-
geom = ml
297+
298+
geom = tmls
260299

261300
case strings.Contains(s, "LINESTRING"):
262301
if s == "LINESTRING EMPTY" {
263302
return orb.LineString{}, nil
264303
}
265-
s = strings.Replace(s, "LINESTRING", "", -1)
266-
s = trimSpaceBrackets(s)
267-
ps := splitByRegexp(s, noParen)
268-
ls := orb.LineString{}
269-
for _, p := range ps {
270-
tp, err := parsePoint(trimSpaceBrackets(p))
304+
305+
s, err := trimSpaceBrackets(strings.ReplaceAll(s, "LINESTRING", ""))
306+
if err != nil {
307+
return nil, err
308+
}
309+
310+
ls := splitByRegexp(s, noParen)
311+
tls := orb.LineString{}
312+
for _, p := range ls {
313+
tp, err := parsePoint(p)
271314
if err != nil {
272315
return nil, err
273316
}
274-
ls = append(ls, tp)
317+
318+
tls = append(tls, tp)
275319
}
276-
geom = ls
320+
321+
geom = tls
277322

278323
case strings.Contains(s, "MULTIPOLYGON"):
279324
if s == "MULTIPOLYGON EMPTY" {
280325
return orb.MultiPolygon{}, nil
281326
}
282-
s = strings.Replace(s, "MULTIPOLYGON", "", -1)
283-
mpol := orb.MultiPolygon{}
284-
285-
for _, ps := range splitByRegexp(trimSpaceBrackets(s), doubleParen) {
286-
pol := orb.Polygon{}
287-
for _, ls := range splitByRegexp(trimSpaceBrackets(ps), singleParen) {
288-
ring := orb.Ring{}
289-
for _, p := range splitByRegexp(ls, noParen) {
290-
tp, err := parsePoint(trimSpaceBrackets(p))
327+
328+
s, err := trimSpaceBrackets(strings.ReplaceAll(s, "MULTIPOLYGON", ""))
329+
if err != nil {
330+
return nil, err
331+
}
332+
333+
tmpoly := orb.MultiPolygon{}
334+
for _, poly := range splitByRegexp(s, doubleParen) {
335+
poly, err := trimSpaceBrackets(poly)
336+
if err != nil {
337+
return nil, err
338+
}
339+
340+
tpoly := orb.Polygon{}
341+
for _, r := range splitByRegexp(poly, singleParen) {
342+
r, err := trimSpaceBrackets(r)
343+
if err != nil {
344+
return nil, err
345+
}
346+
347+
tr := orb.Ring{}
348+
for _, p := range splitByRegexp(r, noParen) {
349+
tp, err := parsePoint(p)
291350
if err != nil {
292351
return nil, err
293352
}
294-
ring = append(ring, tp)
353+
354+
tr = append(tr, tp)
295355
}
296-
pol = append(pol, ring)
356+
357+
tpoly = append(tpoly, tr)
297358
}
298-
mpol = append(mpol, pol)
359+
360+
tmpoly = append(tmpoly, tpoly)
299361
}
300-
geom = mpol
362+
363+
geom = tmpoly
301364

302365
case strings.Contains(s, "POLYGON"):
303366
if s == "POLYGON EMPTY" {
304367
return orb.Polygon{}, nil
305368
}
306-
s = strings.Replace(s, "POLYGON", "", -1)
307-
s = trimSpaceBrackets(s)
308-
309-
rs := splitByRegexp(s, singleParen)
310-
pol := make(orb.Polygon, 0, len(rs))
311-
for _, r := range rs {
312-
ps := splitByRegexp(trimSpaceBrackets(r), noParen)
313-
ring := orb.Ring{}
369+
370+
s, err := trimSpaceBrackets(strings.ReplaceAll(s, "POLYGON", ""))
371+
if err != nil {
372+
return nil, err
373+
}
374+
375+
rings := splitByRegexp(s, singleParen)
376+
tpoly := make(orb.Polygon, 0, len(rings))
377+
for _, r := range rings {
378+
r, err := trimSpaceBrackets(r)
379+
if err != nil {
380+
return nil, err
381+
}
382+
383+
ps := splitByRegexp(r, noParen)
384+
tring := orb.Ring{}
314385
for _, p := range ps {
315-
tp, err := parsePoint(trimSpaceBrackets(p))
386+
tp, err := parsePoint(p)
316387
if err != nil {
317388
return nil, err
318389
}
319-
ring = append(ring, tp)
390+
tring = append(tring, tp)
320391
}
321-
pol = append(pol, ring)
392+
tpoly = append(tpoly, tring)
322393
}
323-
geom = pol
394+
geom = tpoly
324395
default:
325396
return nil, ErrUnsupportedGeometry
326397
}
@@ -329,12 +400,12 @@ func Unmarshal(s string) (geom orb.Geometry, err error) {
329400
}
330401

331402
func splitByRegexp(s string, re *regexp.Regexp) []string {
332-
indexes := re.FindAllStringIndex(s, -1)
403+
indexes := re.FindAllStringSubmatchIndex(s, -1)
333404
start := 0
334405
result := make([]string, len(indexes)+1)
335406
for i, element := range indexes {
336-
result[i] = s[start:element[0]]
337-
start = element[1]
407+
result[i] = s[start:element[2]]
408+
start = element[3]
338409
}
339410
result[len(indexes)] = s[start:]
340411
return result

0 commit comments

Comments
 (0)