Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
[compat]
CEnum = "0.4, 0.5"
ColorTypes = "0.10, 0.11"
Dates = "<0.0.1,1"
Dates = "<0.0.1, 1"
DiskArrays = "0.3, 0.4"
Extents = "0.1"
GDAL = "1.7"
GDAL = "1.8"
GeoFormatTypes = "0.4.2"
GeoInterface = "1"
GeoInterfaceMakie = "0.1"
Expand Down
1 change: 1 addition & 0 deletions src/ArchGDAL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ include("ogr/featurelayer.jl")
include("ogr/featuredefn.jl")
include("ogr/fielddefn.jl")
include("ogr/styletable.jl")
include("mdarray/mdarray.jl")
include("utilities.jl")
include("context.jl")
include("base/iterators.jl")
Expand Down
372 changes: 372 additions & 0 deletions src/mdarray/mdarray.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,372 @@
abstract type AbstractExtendedDataType end
# needs to have a `ptr::GDALExtendedDataTypeH` attribute

abstract type AbstractEDTComponent end
# needs to have a `ptr::GDALEDTComponentH` attribute

abstract type AbstractGroup end
# needs to have a `ptr::GDAL.GDALGroupH` attribute

abstract type AbstractMDArray end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want this to be <: AbstractDiskArray so chunked reads work automatically.

# needs to have a `ptr::GDAL.GDALMDArrayH` attribute

abstract type AbstractAttribute end
# needs to have a `ptr::GDAL.GDALAttributeH` attribute

abstract type AbstractDimension end
# needs to have a `ptr::GDAL.GDALDimensionH` attribute

################################################################################

# Question: Why do the `I...` types exist? The only difference seems
# to be that they call a finalizer. This could instead be an option to
# the constructor, simplifying the type hierarchy.

mutable struct ExtendedDataType <: AbstractExtendedDataType
ptr::GDAL.GDALExtendedDataTypeH
end

mutable struct EDTComponent <: AbstractEDTComponent
ptr::GDAL.GDALEDTComponentH
end

mutable struct Group <: AbstractGroup
ptr::GDAL.GDALGroupH

Group(ptr::GDAL.GDALGroupH = C_NULL) = new(ptr)
end

mutable struct IGroup <: AbstractGroup
ptr::GDAL.GDALGroupH

function IGroup(ptr::GDAL.GDALGroupH = C_NULL)
group = new(ptr)
finalizer(destroy, group)
return group
end
end

mutable struct MDArray <: AbstractMDArray
ptr::GDAL.GDALMDArrayH

MDArray(ptr::GDAL.GDALMDArrayH = C_NULL) = new(ptr)
end

mutable struct IMDArray <: AbstractMDArray
ptr::GDAL.GDALMDArrayH

function IMDArray(ptr::GDAL.GDALMDArrayH = C_NULL)
mdarray = new(ptr)
finalizer(destroy, mdarray)
return mdarray
end
end

mutable struct Attribute <: AbstractAttribute
ptr::GDAL.GDALAttributeH

Attribute(ptr::GDAL.GDALAttributeH = C_NULL) = new(ptr)
end

mutable struct IAttribute <: AbstractAttribute
ptr::GDAL.GDALAttributeH

function IAttribute(ptr::GDAL.GDALAttributeH = C_NULL)
attribute = new(ptr)
finalizer(destroy, attribute)
return attribute
end
end

mutable struct Dimension <: AbstractDimension
ptr::GDAL.GDALDimensionH

Dimension(ptr::GDAL.GDALDimensionH = C_NULL) = new(ptr)
end

mutable struct IDimension <: AbstractDimension
ptr::GDAL.GDALDimensionH

function IDimension(ptr::GDAL.GDALDimensionH = C_NULL)
dimension = new(ptr)
finalizer(destroy, dimension)
return dimension
end
end

################################################################################

Base.unsafe_convert(::Type{Ptr{Cvoid}}, x::AbstractExtendedDataType) = x.ptr
Base.unsafe_convert(::Type{Ptr{Cvoid}}, x::AbstractEDTComponent) = x.ptr
Base.unsafe_convert(::Type{Ptr{Cvoid}}, x::AbstractGroup) = x.ptr
Base.unsafe_convert(::Type{Ptr{Cvoid}}, x::AbstractMDArray) = x.ptr
Base.unsafe_convert(::Type{Ptr{Cvoid}}, x::AbstractAttribute) = x.ptr
Base.unsafe_convert(::Type{Ptr{Cvoid}}, x::AbstractDimension) = x.ptr

################################################################################

function destroy(datatype::AbstractExtendedDataType)::Nothing
GDAL.gdalextendeddatatyperelease(datatype)
datatype.ptr = C_NULL
return nothing
end

function destroy(edtcomponent::AbstractEDTComponent)::Nothing
GDAL.gdaledtcomponentrelease(edtcomponent)
edtcomponent.ptr = C_NULL
return nothing
end

function destroy(group::AbstractGroup)::Nothing
GDAL.gdalgrouprelease(group)
group.ptr = C_NULL
return nothing
end

function destroy(mdarray::AbstractMDArray)::Nothing
GDAL.gdalmdarrayrelease(mdarray)
mdarray.ptr = C_NULL
return nothing
end

function destroy(attribute::AbstractAttribute)::Nothing
GDAL.gdalattributerelease(attribute)
attribute.ptr = C_NULL
return nothing
end

function destroy(dimension::AbstractDimension)::Nothing
GDAL.gdaldimensionrelease(dimension)
dimension.ptr = C_NULL
return nothing
end

################################################################################

# GDALGroup

function getname(group::AbstractGroup)::AbstractString
return GDAL.gdalgroupgetname(group)
end

function getfullname(group::AbstractGroup)::AbstractString
return GDAL.gdalgroupgetfullname(group)
end

function getmdarraynames(
group::AbstractGroup,
options = nothing,
)::AbstractVector{<:AbstractString}
# TODO: allow options
@assert options === nothing
return GDAL.gdalgroupgetmdarraynames(group, C_NULL)
end

function openmdarray(
group::AbstractGroup,
name::AbstractString,
options,
)::AbstractMDArray
# TODO: allow options
@assert options === nothing
return IMDArray(GDAL.gdalgroupopenmdarray(group, name, C_NULL))
end

function getgroupnames(
group::AbstractGroup,
options = nothing,
)::AbstractVector{<:AbstractString}
# TODO: allow options
@assert options === nothing
return GDAL.gdalgroupgetgroupnames(group, C_NULL)
end

function opengroup(
group::AbstractGroup,
name::AbstractString,
options,
)::AbstractGroup
# TODO: allow options
@assert options === nothing
return IGroup(GDAL.gdalgroupopengroup(group, name, C_NULL))
end

function getvectorlayernames(
group::AbstractGroup,
options,
)::AbstractVector{<:AbstractString}
# TODO: allow options
@assert options === nothing
return GDAL.gdalgroupgetvectorlayernames(group, C_NULL)
end

function openvectorlayer(group::AbstractGroup, options)::AbstractFeatureLayer
# TODO: allow options
@assert options === nothing
# TODO: Find out how to set `ownedby` and `spatialref`, probably by querying `group`
return IFeatureLayer(
GDAL.openvectorlayer(group, C_NULL),
ownedby,
spatialref,
)
end

function getdimensions(
group::AbstractGroup,
options,
)::AbstractVector{<:AbstractDimension}
# TODO: allow options
@assert options === nothing
dimensioncountref = Ref{Csize_t}()
dimensionshptr = GDAL.gdalgroupgetdimensions(group, ndimensions, C_NULL)
dimensions = AbstractDimension[
IDimension(unsafe_load(dimensionhptr, n)) for
n in 1:dimensionscountref[]
]
GDAL.vsifree(dimensionshptr)
return dimensions
end

function creategroup(
group::AbstractGroup,
name::AbstractString,
options,
)::AbstractGroup
# TODO: allow options
@assert options === nothing
return IGroup(GDAL.gdalgroupcreategroup(group, name, C_NULL))
end

function deletegroup(group::AbstractGroup, name::AbstractString, options)::Bool
# TODO: allow options
@assert options === nothing
return GDAL.gdalgroupdeletegroup(group, name, C_NULL)
end

function createdimension(
group::AbstractGroup,
name::AbstractString,
type::AbstractString,
direction::AbstractString,
size::Integer,
options,
)::AbstractDimension
# TODO: allow options
@assert options === nothing
return IDimension(
GDAL.gdalgroupcreatedimension(
group,
name,
type,
direction,
size,
C_NULL,
),
)
end

function createmdarray(
group::AbstractGroup,
name::AbstractString,
dimensions::AbstractVector{<:AbstractDimension},
datatype::AbstractExtendedDataType,
options,
)::AbstractMDArray
# TODO: allow options
@assert options === nothing
dimensionhptrs = Ptr{Cvoid}[convert(Ptr{Cvoid}, dim) for dim in dimensions]
return IMDArray(
GDAL.gdalgroupcreatemdarray(
group,
name,
length(dimensionhptrs),
dimensionhptrs,
datatype,
C_NULL,
),
)
end

function deletemdarray(
group::AbstractGroup,
name::AbstractString,
options,
)::Bool
# TODO: allow options
@assert options === nothing
return GDAL.gdalgroupdeletemdarray(group, name, C_NULL)
end

# gettotalcopycost
# copyfrom

function getstructuralinfo(
group::AbstractGroup,
)::AbstractVector{<:AbstractString}
return GDAL.gdalgroupgetstructuralinfo(group)
end

function openmdarrayfromfullname(
group::AbstractGroup,
fullname::AbstractString,
options,
)::AbstractMDArray
# TODO: allow options
@assert options === nothing
return IMDArray(
GDAL.gdalgroupopenmdarrayfromfullname(group, fullname, C_NULL),
)
end

function resolvemdarray(
group::AbstractGroup,
name::AbstractString,
startingpath::AbstractString,
options,
)::AbstractMDArray
# TODO: allow options
@assert options === nothing
return IMDArray(
GDAL.gdalgroupresolvemdarray(group, name, startingpath, C_NULL),
)
end

function opengroupfromfullname(
group::AbstractGroup,
fullname::AbstractString,
options,
)::AbstractGroup
# TODO: allow options
@assert options === nothing
return IGroup(GDAL.gdalgroupopengroupfromfullname(group, fullname, C_NULL))
end

function opendimensionfromfullname(
group::AbstractGroup,
fullname::AbstractString,
options,
)::AbstractDimension
# TODO: allow options
@assert options === nothing
return IDimension(
GDAL.gdalgroupopendimensionfromfullname(group, fullname, C_NULL),
)
end

# clearstatistics

function rename(group::AbstractGroup, newname::AbstractString)::Bool
return GDAL.gdalgrouprename(group, newname)
end

function subsetdimensionfromselection(
group::AbstractGroup,
selection::AbstractString,
options,
)::AbstractGroup
# TODO: allow options
@assert options === nothing
return IGroup(
GDAL.gdalgroupsubsetdimensionfromselection(group, selection, C_NULL),
)
end