diff --git a/src/variable.jl b/src/variable.jl index ba77e2b6..cf89a8a3 100644 --- a/src/variable.jl +++ b/src/variable.jl @@ -86,11 +86,19 @@ variable(ds::NCDataset,varname::Symbol) = _variable(ds,varname) export variable +function checkbuffer(len,data) + if length(data) != len + throw(DimensionMismatch("expected an array with $(len) elements, but got an arrow with $(length(data)) elements")) + end +end + """ NCDatasets.load!(ncvar::Variable, data, indices) Loads a NetCDF variables `ncvar` in-place and puts the result in `data` along the -specified `indices`. +specified `indices`. One can use @inbounds annotate code where +bounds checking can be elided by the compiler (which typically require +type-stable code). ```julia ds = Dataset("file.nc") @@ -98,6 +106,8 @@ ncv = ds["vgos"].var; # data must have the right shape and type data = zeros(eltype(ncv),size(ncv)); NCDatasets.load!(ncv,data,:,:,:) +# or +# @inbounds NCDatasets.load!(ncv,data,:,:,:) close(ds) # loading a subset @@ -106,19 +116,31 @@ load!(ds["temp"].var,data,:,1) # loads the 1st column ``` """ -@inline function load!(ncvar::Variable{T,N}, data, indices::Union{Integer, UnitRange, StepRange, Colon}...) where {T,N} +@inline function load!(ncvar::Variable{T,N}, data::AbstractArray{T}, indices::Union{Integer, UnitRange, StepRange, Colon}...) where {T,N} sizes = size(ncvar) normalizedindices = normalizeindexes(sizes, indices) ind = to_indices(ncvar,normalizedindices) start,count,stride,jlshape = ncsub(ind) + + @boundscheck begin + checkbounds(ncvar,indices...) + checkbuffer(prod(count),data) + end + nc_get_vars!(ncvar.ds.ncid,ncvar.varid,start,count,stride,data) end -@inline function load!(ncvar::Variable{T,2}, data, i::Colon,j::UnitRange) where T +@inline function load!(ncvar::Variable{T,2}, data::AbstractArray{T}, i::Colon,j::UnitRange) where T # reversed and 0-based start = [first(j)-1,0] count = [length(j),size(ncvar,1)] + + @boundscheck begin + checkbounds(ncvar,i,j) + checkbuffer(prod(count),data) + end + nc_get_vara!(ncvar.ds.ncid,ncvar.varid,start,count,data) end diff --git a/test/test_variable.jl b/test/test_variable.jl index cf8b2d42..cbe8b344 100644 --- a/test/test_variable.jl +++ b/test/test_variable.jl @@ -275,3 +275,16 @@ data = [1,2,3] ncv = defVar(ds,"data",data,("data",)) @test isempty(ncv[Int[]]) close(ds) + +# issue 211 +filename = tempname() +ds = NCDataset(filename, "c") +data = [1,2,3] +ncv = defVar(ds,"data",data,("data",)) +data2 = zeros(Int,1) +# data2 too small +@test_throws DimensionMismatch NCDatasets.load!(ds["data"].var,data2,:) + +data2 = zeros(Int,10) +# asking too many elements +@test_throws BoundsError NCDatasets.load!(ds["data"].var,data2,1:10)