Class: GDAL::CPLErrorHandler

Inherits:
Object
  • Object
show all
Includes:
Logger
Defined in:
lib/gdal/cpl_error_handler.rb

Overview

This is used to override GDAL’s built-in error handling. By default, GDAL only logs errors to STDOUT, which doesn’t allow a whole lot of flexibility. This maps GDAL’s errors to either standard Ruby exceptions or new exceptions defined in this gem. Doing so also lets ffi-gdal users rescue these exceptions, which is beneficial for obvious reasons.

Constant Summary collapse

CPLE_MAP =
[
  { cple: :CPLE_None,           exception: nil },
  { cple: :CPLE_AppDefined,     exception: GDAL::Error },
  { cple: :CPLE_OutOfMemory,    exception: ::NoMemoryError },
  { cple: :CPLE_FileIO,         exception: ::IOError },
  { cple: :CPLE_OpenFailed,     exception: GDAL::OpenFailure },
  { cple: :CPLE_IllegalArg,     exception: ::ArgumentError },
  { cple: :CPLE_NotSupported,   exception: GDAL::UnsupportedOperation },
  { cple: :CPLE_AssertionFailed, exception: ::RuntimeError },
  { cple: :CPLE_NoWriteAccess,  exception: GDAL::NoWriteAccess },
  { cple: :CPLE_UserInterrupt,  exception: ::Interrupt },
  { cple: :CPLE_ObjectNull,     exception: GDAL::NullObject }
].freeze
FAIL_PROC =
lambda do |exception, message|
  ex = exception ? exception.new(message) : GDAL::Error.new(message)
  ex.set_backtrace(caller(3))

  raise(ex)
end
SUCCESS_PROC =
proc { true }

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCPLErrorHandler

Returns a new instance of CPLErrorHandler.



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/gdal/cpl_error_handler.rb', line 66

def initialize
  @on_none = SUCCESS_PROC
  @on_debug = SUCCESS_PROC

  @on_warning = lambda do |_, message|
    warn(message)
    false
  end

  @on_failure = FAIL_PROC
  @on_fatal = FAIL_PROC
end

Instance Attribute Details

#on_debugProc

Returns:

  • (Proc)


55
56
57
# File 'lib/gdal/cpl_error_handler.rb', line 55

def on_debug
  @on_debug
end

#on_failureProc

Returns:

  • (Proc)


61
62
63
# File 'lib/gdal/cpl_error_handler.rb', line 61

def on_failure
  @on_failure
end

#on_fatalProc

Returns:

  • (Proc)


64
65
66
# File 'lib/gdal/cpl_error_handler.rb', line 64

def on_fatal
  @on_fatal
end

#on_noneProc

Returns:

  • (Proc)


52
53
54
# File 'lib/gdal/cpl_error_handler.rb', line 52

def on_none
  @on_none
end

#on_warningProc

Returns:

  • (Proc)


58
59
60
# File 'lib/gdal/cpl_error_handler.rb', line 58

def on_warning
  @on_warning
end

Class Method Details

.handle_errorProc

Returns:

  • (Proc)


36
37
38
# File 'lib/gdal/cpl_error_handler.rb', line 36

def self.handle_error
  new.handler_lambda
end

.manually_handle(message) ⇒ Object

Parameters:

  • message (String)

    Exception message if the block returns something that should cause a raise.

Raises:



43
44
45
46
47
48
49
# File 'lib/gdal/cpl_error_handler.rb', line 43

def self.manually_handle(message)
  cpl_err = yield

  case cpl_err
  when :CE_Fatal, :CE_Failure then raise GDAL::Error, message
  end
end

Instance Method Details

#custom_handleObject

Use this when you want to override the default event handling. For example, you may want to return a value in the case of a :CE_Warning. To do so, you need to create a new ErrorHandler object, assign a new Proc by calling #on_warning=, then call this method with your wrapped CPLErr-returning function in a block. That might look something like:

handler = GDAL::ErrorHandler.new
handler.on_warning = -> { warn 'Uh oh!'; return Array.new }
handler.custom_handle do
  FFI::GDAL.DoSomeStuff()
end

After this code gets called, error handling will return to normal.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/gdal/cpl_error_handler.rb', line 106

def custom_handle
  FFI::CPL::Error.CPLPushErrorHandler(handler_lambda)
  yield

  msg, ptr = FFI::CPL::Error.CPLGetLastErrorMsg
  ptr.autorelease = false

  r = result(FFI::CPL::Error.CPLGetLastErrorType,
             FFI::CPL::Error.CPLGetLastErrorNo,
             msg)
  FFI::CPL::Error.CPLErrorReset
  FFI::CPL::Error.CPLPopErrorHandler

  r
end

#handler_lambdaProc

Looks up the error class then calls the appropriate on_ proc, thus handling various error/non-error scenarios. More info here: www.gdal.org/cpl__error_8h.html#a74d0e649d58180e621540bf73b58e4a2.

Returns:

  • (Proc)

    A lambda that adheres to the CPL Error interface.



84
85
86
87
88
89
90
91
# File 'lib/gdal/cpl_error_handler.rb', line 84

def handler_lambda
  @handler_lambda ||= lambda do |error_class, error_number, message|
    r = result(error_class, error_number, message)
    FFI::CPL::Error.CPLErrorReset

    r
  end
end