Skip to content

Commit 7d7bba0

Browse files
authored
Enable more exotic types in reading and writing. (#284)
* Enable more exotic types in reading and writing. * Added tests, forced conversion for subtypes. * Fixed failing test due to duplicate fieldname. * Extended test coverage. * Unified setfield calls by removing `convert`s.
1 parent 7c05b74 commit 7d7bba0

File tree

5 files changed

+144
-32
lines changed

5 files changed

+144
-32
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ uuid = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
33
keywords = ["GDAL", "IO"]
44
license = "MIT"
55
desc = "A high level API for GDAL - Geospatial Data Abstraction Library"
6-
version = "0.8.2"
6+
version = "0.8.3"
77

88
[deps]
99
CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82"

src/ogr/feature.jl

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,30 @@ end
218218
# Cint),arg1,arg2)
219219
# end
220220

221+
"""
222+
asbool(feature::Feature, i::Integer)
223+
224+
Fetch field value as a boolean
225+
226+
### Parameters
227+
* `feature`: the feature that owned the field.
228+
* `i`: the field to fetch, from 0 to GetFieldCount()-1.
229+
"""
230+
asbool(feature::Feature, i::Integer)::Bool =
231+
convert(Bool, GDAL.ogr_f_getfieldasinteger(feature.ptr, i))
232+
233+
"""
234+
asint16(feature::Feature, i::Integer)
235+
236+
Fetch field value as integer 16 bit.
237+
238+
### Parameters
239+
* `feature`: the feature that owned the field.
240+
* `i`: the field to fetch, from 0 to GetFieldCount()-1.
241+
"""
242+
asint16(feature::Feature, i::Integer)::Int16 =
243+
convert(Int16, GDAL.ogr_f_getfieldasinteger(feature.ptr, i))
244+
221245
"""
222246
asint(feature::Feature, i::Integer)
223247
@@ -242,6 +266,18 @@ Fetch field value as integer 64 bit.
242266
asint64(feature::Feature, i::Integer)::Int64 =
243267
GDAL.ogr_f_getfieldasinteger64(feature.ptr, i)
244268

269+
"""
270+
assingle(feature::Feature, i::Integer)
271+
272+
Fetch field value as a single.
273+
274+
### Parameters
275+
* `feature`: the feature that owned the field.
276+
* `i`: the field to fetch, from 0 to GetFieldCount()-1.
277+
"""
278+
assingle(feature::Feature, i::Integer)::Float32 =
279+
convert(Float32, GDAL.ogr_f_getfieldasdouble(feature.ptr, i))
280+
245281
"""
246282
asdouble(feature::Feature, i::Integer)
247283
@@ -440,7 +476,7 @@ end
440476

441477
getfield(feature::Feature, i::Nothing)::Missing = missing
442478

443-
const _FETCHFIELD = Dict{OGRFieldType,Function}(
479+
const _FETCHFIELD = Dict{Union{OGRFieldType,OGRFieldSubType},Function}(
444480
OFTInteger => asint,
445481
OFTIntegerList => asintlist,
446482
OFTReal => asdouble,
@@ -453,6 +489,9 @@ const _FETCHFIELD = Dict{OGRFieldType,Function}(
453489
OFTDateTime => asdatetime,
454490
OFTInteger64 => asint64,
455491
OFTInteger64List => asint64list,
492+
OFSTBoolean => asbool,
493+
OFSTInt16 => asint16,
494+
OFSTFloat32 => assingle,
456495
)
457496

458497
"""
@@ -528,32 +567,29 @@ function setfield!(feature::Feature, i::Integer, value::Missing)::Feature
528567
return feature
529568
end
530569

531-
function setfield!(feature::Feature, i::Integer, value::Int32)::Feature
532-
GDAL.ogr_f_setfieldinteger(feature.ptr, i, value)
533-
return feature
534-
end
535-
536-
function setfield!(feature::Feature, i::Integer, value::Int16)::Feature
537-
GDAL.ogr_f_setfieldinteger(feature.ptr, i, value)
538-
return feature
539-
end
540-
541-
function setfield!(feature::Feature, i::Integer, value::Bool)::Feature
570+
function setfield!(
571+
feature::Feature,
572+
i::Integer,
573+
value::Union{Bool,UInt8,Int8,UInt16,Int16,Int32},
574+
)::Feature
542575
GDAL.ogr_f_setfieldinteger(feature.ptr, i, value)
543576
return feature
544577
end
545578

546-
function setfield!(feature::Feature, i::Integer, value::Int64)::Feature
579+
function setfield!(
580+
feature::Feature,
581+
i::Integer,
582+
value::Union{UInt32,Int64},
583+
)::Feature
547584
GDAL.ogr_f_setfieldinteger64(feature.ptr, i, value)
548585
return feature
549586
end
550587

551-
function setfield!(feature::Feature, i::Integer, value::Float32)::Feature
552-
GDAL.ogr_f_setfielddouble(feature.ptr, i, value)
553-
return feature
554-
end
555-
556-
function setfield!(feature::Feature, i::Integer, value::Float64)::Feature
588+
function setfield!(
589+
feature::Feature,
590+
i::Integer,
591+
value::Union{Float16,Float32,Float64},
592+
)::Feature
557593
GDAL.ogr_f_setfielddouble(feature.ptr, i, value)
558594
return feature
559595
end

src/types.jl

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,19 +311,30 @@ end
311311
@convert(
312312
OGRFieldType::DataType,
313313
OFTInteger::Bool,
314+
OFTInteger::UInt8,
315+
OFTInteger::Int8,
316+
OFTInteger::UInt16,
314317
OFTInteger::Int16,
315318
OFTInteger::Int32, # default type comes last
316-
OFTIntegerList::Vector{Int32},
319+
OFTIntegerList::Vector{Int8},
320+
OFTIntegerList::Vector{Int16},
321+
OFTIntegerList::Vector{UInt16},
322+
OFTIntegerList::Vector{Int32}, # default type comes last
323+
OFTReal::Float16,
317324
OFTReal::Float32,
318325
OFTReal::Float64, # default type comes last
326+
OFTRealList::Vector{Float16},
327+
OFTRealList::Vector{Float32},
319328
OFTRealList::Vector{Float64},
320329
OFTString::String,
321330
OFTStringList::Vector{String},
322331
OFTBinary::Vector{UInt8},
323332
OFTDate::Dates.Date,
324333
OFTTime::Dates.Time,
325334
OFTDateTime::Dates.DateTime,
326-
OFTInteger64::Int64,
335+
OFTInteger64::UInt32,
336+
OFTInteger64::Int64, # default type comes last
337+
OFTInteger64List::Vector{UInt32},
327338
OFTInteger64List::Vector{Int64},
328339
)
329340

@@ -338,11 +349,35 @@ end
338349

339350
@convert(
340351
OGRFieldSubType::DataType,
341-
OFSTNone::Nothing,
342-
OFSTBoolean::Bool,
343-
OFSTInt16::Int16,
344-
OFSTFloat32::Float32,
345-
OFSTJSON::String,
352+
OFSTBoolean::Vector{Bool},
353+
OFSTBoolean::Bool, # default type comes last
354+
OFSTInt16::UInt8,
355+
OFSTInt16::Int8,
356+
OFSTInt16::Vector{Int8},
357+
OFSTInt16::Vector{Int16},
358+
OFSTInt16::Int16, # default type comes last
359+
OFSTFloat32::Float16,
360+
OFSTFloat32::Vector{Float16},
361+
OFSTFloat32::Vector{Float32},
362+
OFSTFloat32::Float32, # default type comes last
363+
OFSTNone::UInt16,
364+
OFSTNone::Vector{UInt16},
365+
OFSTNone::Int32,
366+
OFSTNone::Vector{Int32},
367+
OFSTNone::Float64,
368+
OFSTNone::Vector{Float64},
369+
OFSTNone::String,
370+
OFSTNone::Vector{String},
371+
OFSTNone::Vector{UInt8},
372+
OFSTNone::Dates.Date,
373+
OFSTNone::Dates.Time,
374+
OFSTNone::Dates.DateTime,
375+
OFSTNone::UInt32,
376+
OFSTNone::Vector{UInt32},
377+
OFSTNone::Int64,
378+
OFSTNone::Vector{Int64},
379+
# Lacking OFSTUUID and OFSTJSON defined in GDAL ≥ v"3.3"
380+
OFSTNone::Nothing, # default type comes last
346381
)
347382

348383
@convert(

test/test_convert.jl

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,26 @@ import GeoFormatTypes as GFT
5151
end
5252

5353
@testset "type conversions" begin
54-
@test convert(AG.OGRFieldType, Int32) == AG.OFTInteger
55-
@test convert(AG.OGRFieldType, Int16) == AG.OFTInteger
5654
@test convert(AG.OGRFieldType, Bool) == AG.OFTInteger
55+
@test convert(AG.OGRFieldType, UInt8) == AG.OFTInteger
56+
@test convert(AG.OGRFieldType, Int8) == AG.OFTInteger
57+
@test convert(AG.OGRFieldType, UInt16) == AG.OFTInteger
58+
@test convert(AG.OGRFieldType, Int16) == AG.OFTInteger
59+
@test convert(AG.OGRFieldType, UInt32) == AG.OFTInteger64
60+
@test convert(AG.OGRFieldType, Int32) == AG.OFTInteger
61+
@test convert(AG.OGRFieldType, Int64) == AG.OFTInteger64
5762

63+
@test convert(AG.OGRFieldType, Float16) == AG.OFTReal
5864
@test convert(AG.OGRFieldType, Float32) == AG.OFTReal
5965
@test convert(AG.OGRFieldType, Float64) == AG.OFTReal
6066

6167
# Reverse conversion should result in default type, not subtype
68+
@test convert(DataType, AG.OFSTBoolean) == Bool
69+
@test convert(DataType, AG.OFSTInt16) == Int16
6270
@test convert(DataType, AG.OFTInteger) == Int32
71+
@test convert(DataType, AG.OFTInteger64) == Int64
72+
@test convert(DataType, AG.OFSTFloat32) == Float32
6373
@test convert(DataType, AG.OFTReal) == Float64
74+
@test convert(DataType, AG.OFSTNone) == Nothing
6475
end
6576
end

test/test_feature.jl

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,26 @@ import ArchGDAL as AG
220220
AG.createfielddefn("int32field", AG.OFTInteger) do fielddefn
221221
return AG.addfielddefn!(layer, fielddefn)
222222
end
223-
AG.createfielddefn("float32field", AG.OFTReal) do fielddefn
223+
AG.createfielddefn("booleansubfield", AG.OFTInteger) do fielddefn
224+
AG.setsubtype!(fielddefn, AG.OFSTBoolean)
225+
return AG.addfielddefn!(layer, fielddefn)
226+
end
227+
AG.createfielddefn("int16subfield", AG.OFTInteger) do fielddefn
228+
AG.setsubtype!(fielddefn, AG.OFSTInt16)
229+
return AG.addfielddefn!(layer, fielddefn)
230+
end
231+
AG.createfielddefn("float32subfield", AG.OFTReal) do fielddefn
232+
AG.setsubtype!(fielddefn, AG.OFSTFloat32)
233+
return AG.addfielddefn!(layer, fielddefn)
234+
end
235+
AG.createfielddefn("float16subfield", AG.OFTReal) do fielddefn
236+
AG.setsubtype!(fielddefn, AG.OFSTFloat32)
237+
return AG.addfielddefn!(layer, fielddefn)
238+
end
239+
AG.createfielddefn("uint1616subfield", AG.OFTInteger) do fielddefn
240+
return AG.addfielddefn!(layer, fielddefn)
241+
end
242+
AG.createfielddefn("uint32subfield", AG.OFTInteger64) do fielddefn
224243
return AG.addfielddefn!(layer, fielddefn)
225244
end
226245
AG.createfeature(layer) do feature
@@ -235,7 +254,12 @@ import ArchGDAL as AG
235254
AG.setfield!(feature, 8, true)
236255
AG.setfield!(feature, 9, Int16(1))
237256
AG.setfield!(feature, 10, Int32(1))
238-
AG.setfield!(feature, 11, Float32(1.0))
257+
AG.setfield!(feature, 11, false)
258+
AG.setfield!(feature, 12, Int8(1))
259+
AG.setfield!(feature, 13, Float32(1.0))
260+
AG.setfield!(feature, 14, Float16(1.0))
261+
AG.setfield!(feature, 15, UInt16(1.0))
262+
AG.setfield!(feature, 16, UInt32(1.0))
239263
for i in 1:AG.nfield(feature)
240264
@test !AG.isfieldnull(feature, i - 1)
241265
@test AG.isfieldsetandnotnull(feature, i - 1)
@@ -248,6 +272,12 @@ import ArchGDAL as AG
248272
AG.getgeom(feature, 0) do geom
249273
@test sprint(print, geom) == "NULL Geometry"
250274
end
275+
@test AG.getfield(feature, 11) === false
276+
@test AG.getfield(feature, 12) === Int16(1) # Widened from Int8
277+
@test AG.getfield(feature, 13) === Float32(1.0)
278+
@test AG.getfield(feature, 14) === Float32(1.0) # Widened from Float16
279+
@test AG.getfield(feature, 15) === Int32(1) # Widened from UInt16
280+
@test AG.getfield(feature, 16) === Int64(1) # Widened from UInt32
251281

252282
AG.addfeature(layer) do newfeature
253283
AG.setfrom!(newfeature, feature)
@@ -267,7 +297,7 @@ import ArchGDAL as AG
267297
@test AG.getfield(newfeature, 8) == true
268298
@test AG.getfield(newfeature, 9) == 1
269299
@test AG.getfield(newfeature, 10) == 1
270-
@test AG.getfield(newfeature, 11) == 1.0
300+
@test AG.getfield(newfeature, 13) === Float32(1.0)
271301

272302
AG.createfeature(layer) do lastfeature
273303
AG.setfrom!(lastfeature, feature)

0 commit comments

Comments
 (0)