diff --git a/Project.toml b/Project.toml index 0ded9fd6..9c04d2d1 100644 --- a/Project.toml +++ b/Project.toml @@ -3,7 +3,7 @@ uuid = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3" keywords = ["GDAL", "IO"] license = "MIT" desc = "A high level API for GDAL - Geospatial Data Abstraction Library" -version = "0.8.2" +version = "0.8.3" [deps] CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82" diff --git a/src/ogr/feature.jl b/src/ogr/feature.jl index 42d5c9ab..b304489b 100644 --- a/src/ogr/feature.jl +++ b/src/ogr/feature.jl @@ -218,6 +218,30 @@ end # Cint),arg1,arg2) # end +""" + asbool(feature::Feature, i::Integer) + +Fetch field value as a boolean + +### Parameters +* `feature`: the feature that owned the field. +* `i`: the field to fetch, from 0 to GetFieldCount()-1. +""" +asbool(feature::Feature, i::Integer)::Bool = + convert(Bool, GDAL.ogr_f_getfieldasinteger(feature.ptr, i)) + +""" + asint16(feature::Feature, i::Integer) + +Fetch field value as integer 16 bit. + +### Parameters +* `feature`: the feature that owned the field. +* `i`: the field to fetch, from 0 to GetFieldCount()-1. +""" +asint16(feature::Feature, i::Integer)::Int16 = + convert(Int16, GDAL.ogr_f_getfieldasinteger(feature.ptr, i)) + """ asint(feature::Feature, i::Integer) @@ -242,6 +266,18 @@ Fetch field value as integer 64 bit. asint64(feature::Feature, i::Integer)::Int64 = GDAL.ogr_f_getfieldasinteger64(feature.ptr, i) +""" +assingle(feature::Feature, i::Integer) + +Fetch field value as a single. + +### Parameters +* `feature`: the feature that owned the field. +* `i`: the field to fetch, from 0 to GetFieldCount()-1. +""" +assingle(feature::Feature, i::Integer)::Float32 = + convert(Float32, GDAL.ogr_f_getfieldasdouble(feature.ptr, i)) + """ asdouble(feature::Feature, i::Integer) @@ -440,7 +476,7 @@ end getfield(feature::Feature, i::Nothing)::Missing = missing -const _FETCHFIELD = Dict{OGRFieldType,Function}( +const _FETCHFIELD = Dict{Union{OGRFieldType,OGRFieldSubType},Function}( OFTInteger => asint, OFTIntegerList => asintlist, OFTReal => asdouble, @@ -453,6 +489,9 @@ const _FETCHFIELD = Dict{OGRFieldType,Function}( OFTDateTime => asdatetime, OFTInteger64 => asint64, OFTInteger64List => asint64list, + OFSTBoolean => asbool, + OFSTInt16 => asint16, + OFSTFloat32 => assingle, ) """ @@ -528,32 +567,29 @@ function setfield!(feature::Feature, i::Integer, value::Missing)::Feature return feature end -function setfield!(feature::Feature, i::Integer, value::Int32)::Feature - GDAL.ogr_f_setfieldinteger(feature.ptr, i, value) - return feature -end - -function setfield!(feature::Feature, i::Integer, value::Int16)::Feature - GDAL.ogr_f_setfieldinteger(feature.ptr, i, value) - return feature -end - -function setfield!(feature::Feature, i::Integer, value::Bool)::Feature +function setfield!( + feature::Feature, + i::Integer, + value::Union{Bool,UInt8,Int8,UInt16,Int16,Int32}, +)::Feature GDAL.ogr_f_setfieldinteger(feature.ptr, i, value) return feature end -function setfield!(feature::Feature, i::Integer, value::Int64)::Feature +function setfield!( + feature::Feature, + i::Integer, + value::Union{UInt32,Int64}, +)::Feature GDAL.ogr_f_setfieldinteger64(feature.ptr, i, value) return feature end -function setfield!(feature::Feature, i::Integer, value::Float32)::Feature - GDAL.ogr_f_setfielddouble(feature.ptr, i, value) - return feature -end - -function setfield!(feature::Feature, i::Integer, value::Float64)::Feature +function setfield!( + feature::Feature, + i::Integer, + value::Union{Float16,Float32,Float64}, +)::Feature GDAL.ogr_f_setfielddouble(feature.ptr, i, value) return feature end diff --git a/src/types.jl b/src/types.jl index d33b8b73..23934e2e 100644 --- a/src/types.jl +++ b/src/types.jl @@ -311,11 +311,20 @@ end @convert( OGRFieldType::DataType, OFTInteger::Bool, + OFTInteger::UInt8, + OFTInteger::Int8, + OFTInteger::UInt16, OFTInteger::Int16, OFTInteger::Int32, # default type comes last - OFTIntegerList::Vector{Int32}, + OFTIntegerList::Vector{Int8}, + OFTIntegerList::Vector{Int16}, + OFTIntegerList::Vector{UInt16}, + OFTIntegerList::Vector{Int32}, # default type comes last + OFTReal::Float16, OFTReal::Float32, OFTReal::Float64, # default type comes last + OFTRealList::Vector{Float16}, + OFTRealList::Vector{Float32}, OFTRealList::Vector{Float64}, OFTString::String, OFTStringList::Vector{String}, @@ -323,7 +332,9 @@ end OFTDate::Dates.Date, OFTTime::Dates.Time, OFTDateTime::Dates.DateTime, - OFTInteger64::Int64, + OFTInteger64::UInt32, + OFTInteger64::Int64, # default type comes last + OFTInteger64List::Vector{UInt32}, OFTInteger64List::Vector{Int64}, ) @@ -338,11 +349,35 @@ end @convert( OGRFieldSubType::DataType, - OFSTNone::Nothing, - OFSTBoolean::Bool, - OFSTInt16::Int16, - OFSTFloat32::Float32, - OFSTJSON::String, + OFSTBoolean::Vector{Bool}, + OFSTBoolean::Bool, # default type comes last + OFSTInt16::UInt8, + OFSTInt16::Int8, + OFSTInt16::Vector{Int8}, + OFSTInt16::Vector{Int16}, + OFSTInt16::Int16, # default type comes last + OFSTFloat32::Float16, + OFSTFloat32::Vector{Float16}, + OFSTFloat32::Vector{Float32}, + OFSTFloat32::Float32, # default type comes last + OFSTNone::UInt16, + OFSTNone::Vector{UInt16}, + OFSTNone::Int32, + OFSTNone::Vector{Int32}, + OFSTNone::Float64, + OFSTNone::Vector{Float64}, + OFSTNone::String, + OFSTNone::Vector{String}, + OFSTNone::Vector{UInt8}, + OFSTNone::Dates.Date, + OFSTNone::Dates.Time, + OFSTNone::Dates.DateTime, + OFSTNone::UInt32, + OFSTNone::Vector{UInt32}, + OFSTNone::Int64, + OFSTNone::Vector{Int64}, + # Lacking OFSTUUID and OFSTJSON defined in GDAL ≥ v"3.3" + OFSTNone::Nothing, # default type comes last ) @convert( diff --git a/test/test_convert.jl b/test/test_convert.jl index 38378509..3310e9f0 100644 --- a/test/test_convert.jl +++ b/test/test_convert.jl @@ -51,15 +51,26 @@ import GeoFormatTypes as GFT end @testset "type conversions" begin - @test convert(AG.OGRFieldType, Int32) == AG.OFTInteger - @test convert(AG.OGRFieldType, Int16) == AG.OFTInteger @test convert(AG.OGRFieldType, Bool) == AG.OFTInteger + @test convert(AG.OGRFieldType, UInt8) == AG.OFTInteger + @test convert(AG.OGRFieldType, Int8) == AG.OFTInteger + @test convert(AG.OGRFieldType, UInt16) == AG.OFTInteger + @test convert(AG.OGRFieldType, Int16) == AG.OFTInteger + @test convert(AG.OGRFieldType, UInt32) == AG.OFTInteger64 + @test convert(AG.OGRFieldType, Int32) == AG.OFTInteger + @test convert(AG.OGRFieldType, Int64) == AG.OFTInteger64 + @test convert(AG.OGRFieldType, Float16) == AG.OFTReal @test convert(AG.OGRFieldType, Float32) == AG.OFTReal @test convert(AG.OGRFieldType, Float64) == AG.OFTReal # Reverse conversion should result in default type, not subtype + @test convert(DataType, AG.OFSTBoolean) == Bool + @test convert(DataType, AG.OFSTInt16) == Int16 @test convert(DataType, AG.OFTInteger) == Int32 + @test convert(DataType, AG.OFTInteger64) == Int64 + @test convert(DataType, AG.OFSTFloat32) == Float32 @test convert(DataType, AG.OFTReal) == Float64 + @test convert(DataType, AG.OFSTNone) == Nothing end end diff --git a/test/test_feature.jl b/test/test_feature.jl index 2778005b..2b3390af 100644 --- a/test/test_feature.jl +++ b/test/test_feature.jl @@ -220,7 +220,26 @@ import ArchGDAL as AG AG.createfielddefn("int32field", AG.OFTInteger) do fielddefn return AG.addfielddefn!(layer, fielddefn) end - AG.createfielddefn("float32field", AG.OFTReal) do fielddefn + AG.createfielddefn("booleansubfield", AG.OFTInteger) do fielddefn + AG.setsubtype!(fielddefn, AG.OFSTBoolean) + return AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("int16subfield", AG.OFTInteger) do fielddefn + AG.setsubtype!(fielddefn, AG.OFSTInt16) + return AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("float32subfield", AG.OFTReal) do fielddefn + AG.setsubtype!(fielddefn, AG.OFSTFloat32) + return AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("float16subfield", AG.OFTReal) do fielddefn + AG.setsubtype!(fielddefn, AG.OFSTFloat32) + return AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("uint1616subfield", AG.OFTInteger) do fielddefn + return AG.addfielddefn!(layer, fielddefn) + end + AG.createfielddefn("uint32subfield", AG.OFTInteger64) do fielddefn return AG.addfielddefn!(layer, fielddefn) end AG.createfeature(layer) do feature @@ -235,7 +254,12 @@ import ArchGDAL as AG AG.setfield!(feature, 8, true) AG.setfield!(feature, 9, Int16(1)) AG.setfield!(feature, 10, Int32(1)) - AG.setfield!(feature, 11, Float32(1.0)) + AG.setfield!(feature, 11, false) + AG.setfield!(feature, 12, Int8(1)) + AG.setfield!(feature, 13, Float32(1.0)) + AG.setfield!(feature, 14, Float16(1.0)) + AG.setfield!(feature, 15, UInt16(1.0)) + AG.setfield!(feature, 16, UInt32(1.0)) for i in 1:AG.nfield(feature) @test !AG.isfieldnull(feature, i - 1) @test AG.isfieldsetandnotnull(feature, i - 1) @@ -248,6 +272,12 @@ import ArchGDAL as AG AG.getgeom(feature, 0) do geom @test sprint(print, geom) == "NULL Geometry" end + @test AG.getfield(feature, 11) === false + @test AG.getfield(feature, 12) === Int16(1) # Widened from Int8 + @test AG.getfield(feature, 13) === Float32(1.0) + @test AG.getfield(feature, 14) === Float32(1.0) # Widened from Float16 + @test AG.getfield(feature, 15) === Int32(1) # Widened from UInt16 + @test AG.getfield(feature, 16) === Int64(1) # Widened from UInt32 AG.addfeature(layer) do newfeature AG.setfrom!(newfeature, feature) @@ -267,7 +297,7 @@ import ArchGDAL as AG @test AG.getfield(newfeature, 8) == true @test AG.getfield(newfeature, 9) == 1 @test AG.getfield(newfeature, 10) == 1 - @test AG.getfield(newfeature, 11) == 1.0 + @test AG.getfield(newfeature, 13) === Float32(1.0) AG.createfeature(layer) do lastfeature AG.setfrom!(lastfeature, feature)